COJ 1004: Xi and Bo 并查集

来源:互联网 发布:刺客信条4低配优化 编辑:程序博客网 时间:2024/05/22 01:35

标准代码如下

 # include <stdio.h># define MAXN 105int father[MAXN];int main(){      int T, sta, end, n, m, x, y;     int i;     scanf("%d", &T);     while (T--)     {           scanf("%d%d%d", &sta,&end,&n);           for (i = 0; i < MAXN; ++i)                 father[i] = i;           while (n--)           {                   scanf("%d%d", &m, &x);                   while (x != father[x]) x = father[x];//找到x的根节点,赋给x                   for (i = 2; i <= m; ++i)                   {                     scanf("%d", &y);                     while (y !=father[y] ) y = father[y];//找到y的根节点,赋给y                     if (y != x) father[y] = x;//如果y不是x,则y的根节点为x                    }             }             while (sta != father[sta]) sta = father[sta];//找到起始站的根节点             while (end != father[end]) end = father[end];//找到终点站的根节点             printf(sta==end ? "Yes\n":"No\n");      }     return 0;}//个人代码# include <stdio.h># define MAXN 105int pre[MAXN];int a[MAXN];int main(){      int t,i,j,k,l,m,n,start,end;      scanf("%d",&t);      while(t--)      {        scanf("%d%d%d",&start,&end,&i);        for(l=0;l<MAXN;l++)                pre[l]=l;        while(i--)        {                scanf("%d%d",&j,&n);                for(k=1;k<j;k++)                {                        scanf("%d",&a[k]);                }                while(pre[n]!=n)n=pre[n];                for(k=1;k<j;k++)                {                        m=a[k];                        while(pre[m]!=m)m=pre[m];                        if(m!=n)pre[m]=n;                }      }      while (start != pre[start]) start = pre[start];      while (end != pre[end]) end = pre[end];  printf(start==end ? "Yes\n":"No\n");}return 0;}



并查集由一个整数型的数组和两个函数构成。数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并。

int pre[1000 ];

int find(int x)                                                                                                         //查找根节点

    int r=x;

    while ( pre[r ] != r )                                                                                              //返回根节点 r

          r=pre[r ];

 

    int i=x , j ;

    while( i != r )                                                                                                        //路径压缩

    {

         j = pre[ i ]; // 在改变上级之前用临时变量  j 记录下他的值 

         pre[ i ]= r ; //把上级改为根节点

         i=j;

    }

    return r ;

}

 

 

void join(int x,int y)                                                                                                    //判断x y是否连通,

                                                                                             //如果已经连通,就不用管了 //如果不连通,就把它们所在的连通分支合并起,

{

    int fx=find(x),fy=find(y);

    if(fx!=fy)

        pre[fx ]=fy;

}


搞了一晚上,真是日了狗了。基本思想就是去找点的最终父节点。

0 0
原创粉丝点击