畅通工程 ---并查集

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 int f[1010];//记录当前i的前驱(画完图是树形结构)
 5 
 6 int find(int x) //查找根节点
 7 { 
 8     int r=x;
 9     while(f[r]!=r)
10         r=f[r];
11     int i=x,j;
12     while(i!=r)
13     {
14         j=f[i];
15         f[i]=r;
16         i=j;
17     }
18     return r;
19 }
20 
21 int main()
22 {
23     int n,m,a,b;
24     while(scanf("%d%d",&n,&m),n)
25     {
26         for(int i=0;i<=n;i++)
27             f[i]=i;
28         for(int i=0;i<m;i++)
29         {
30             scanf("%d%d",&a,&b);
31             int x=find(a),y=find(b);//查找祖先,判断x,y是否为一个祖先
32             if(x!=y) // 当ab的帮派不是一个的话,合并 在一起即一个大哥
33                 f[x]=f[y];
34         }
35         int c=0;
36         for(int i=1;i<=n;i++)
37             if(f[i]==i)
38             c++;
39         printf("%d\n",c-1);
40     }
41     return 0;
42 }
43         
View Code

我的理解:

并查集 先是把各个顶点当成一个集合,构成n个集合后,用线段把集合连接起来,判断是否为连通图即判断f数组i位置元素是否等于i,如有一个则为连通图否则为非连通图

find函数把线段的两个顶点x,y找到他所在集合的老大,判断线段的两个端点是否为一个老大,即用f【】数组找,f数组记录的前驱;

找到两个老大之后,如不相等就把两个老大集合,合并起来。

转载于:https://www.cnblogs.com/WDKER/p/5467004.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值