zoukankan      html  css  js  c++  java
  • 种类并查集(POJ 1703)

    1703 -- Find them, Catch them

    http://poj.org/problem?id=1703

    题目大意:有2个敌对帮派,输入D a b表示a,b在不同帮派,输入A a b表示询问a,b是否是在一个帮派。

    题解:因为并查集中的元素均是有联系的,否则也不会被合并到当前集合中。那么我们就把这2个元素之间的关系量转化为一个偏移量,

    假设
    x->y 偏移量0时 x和y同帮派

    x->y 偏移量1时 x和y不同帮派

    不妨继续假设,x的当前集合根节点tx,y的当前集合根节点ty。

    如果tx和ty不相同,那么我们把ty合并到tx上,并且更新deltx[ty]值(注意:deltx[i]表示i的当前集合根节点到i的偏移量!!!!)

    此时 tx->ty = tx->x + x->y + y->ty,可能这一步就是所谓向量思维模式吧

    上式进一步转化为:tx->ty = (deltx[x]+1-deltx[y])%2 = deltx[ty],(模2是保证偏移量取值始终在[0,1]间)

    接下来把这个想法再运用到路径压缩中:

    ffx   

    |     \

    fx      \

    |         /

    |     /

    x     

    路径压缩过程中会将fx的父亲变为x的父亲,所以要改变相对关系,即偏移量。

    ffx->fx+fx->x=ffx->x;

    转换成:delta[x]=(delta[fx]+delta[x])%2;

    int find(int x)
    {
      if(x==fa[x])
        return fa[x];
      int f=fa[x];
      fa[x]=find(fa[x]);
      delta[x]=(delta[x]+delta[f])&1; //这句和上句不能交换位置,delta[]的改变是随着路径压缩是fa[]的改变而改变
      return fa[x];
    }

    #include <stdio.h>
    int n;
    int fa[100001],delta[100001];    //deltx[i]表示i的当前集合根节点到i的偏移量
    void init()
    {
        int i;
        for(i=1;i<=n;i++)
        {
            fa[i]=i;
            delta[i]=0;
        }
    }
    
    int find(int x)
    { 
        if(x==fa[x])
            return fa[x]; 
        int f=fa[x]; 
        fa[x]=find(fa[x]); 
        delta[x]=(delta[x]+delta[f])&1;     //这句和上句不能交换位置,delta[]的改变是随着路径压缩是fa[]的改变而改变
        return fa[x]; 
    }
    
    
    void merge(int x,int y)
    {
        int fx=find(x);
        int fy=find(y);
        if(fx!=fy)
        {
            fa[fy]=fx;
            delta[fy]=(delta[x]+1-delta[y])&1;
        }
    }
    int main()
    {
        int t,m,i,a,b;
        char ch;
        scanf("%d",&t);
        while(t--)
        {
        
            scanf("%d%d%*c",&n,&m);  //%*c替掉回车,ch吃回车,经常搞错,哎。。。
            init();
            for(i=1;i<=m;i++)
            {
                scanf("%c%d%d%*c",&ch,&a,&b);
                if(ch=='D')
                    merge(a,b);
                if(ch=='A')
                {
                    if(find(a)==find(b))
                    {
                        if(delta[a]==delta[b])     //根节点到a和b的偏移量相同时,a和b必定为同一帮派。朋友的朋友是朋友,敌人的敌人也是朋友
                            printf("In the same gang.\n");
                        else
                            printf("In different gangs.\n");
                    }
                    else
                        printf("Not sure yet.\n");
                }
    
            }
            
            
        }
        return 0;
    }
    View Code

  • 相关阅读:
    java8 file转base64
    springboot下maven分环境打包
    maven加载src下的xml文件
    ue正则
    springboot 深坑
    解压版mysql 错误-mysql启动失败
    spring整合activeMQ
    maven分环境 打包
    logger日志配置
    hadoop安装
  • 原文地址:https://www.cnblogs.com/chiry/p/3233459.html
Copyright © 2011-2022 走看看