COJ 1004: Xi and Bo 并查集

本文深入探讨了并查集的基本概念、实现原理及在实际问题中的应用,包括路径压缩和按秩合并策略,通过具体示例展示了如何使用并查集解决连接问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标准代码如下

 # include <stdio.h>


# define MAXN 105


int 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 105


int 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;

}


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值