题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1272
本人若菜,最近做题的时候遇见了这个所以才开始接触并查集。用并查集来检查连通性也就是检查最小生成树。最小生成树的点减去边的差值为一,且在同一个集合内。
因此,判断条件有二:一没有产生回路,二点数减去边数为1;
可以得到如下代码
我们用t来储存点数与边数之差,当产生一条非回路的时候t--,出现一个点t++;
while(scanf("%d %d",&a,&b)&&a||b)
{
if(merge(a,b) == 0)//是已经一个属于同一个集合,也就是说这样就产生了回路~所以直接否掉~
leap = 0;
else//没有产生回路那么边数加1,即点数减一
t--;
if(used[a] == 0)
t++,used[a] =1;
if(used[b] == 0)
t++,used[b] = 1;
}
所以代码如下
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<stdio.h> int set[100005],used[100005],h[100005]; int find(int x) { int r = x; while(r != set[r]) { r = set[r]; } return r; } int merge(int x,int y) { x = find(x); y = find(y); if(x == y) return 0; if(h[x] == h[y]) h[x]++,set[y] = x; else if(h[y] < h[x]) set[y] = x; else set[x] = y; set[x] = y; return 1; } int main() { int a,b,t,i,leap; while(scanf("%d %d",&a,&b) != EOF) { if(a == -1 && b == -1) break; else if(a == 0 && b == 0) { printf("Yes\n"); continue; } for(i = 0;i <= 100000;i++) set[i] = i,used[i] = h[i]= 0; merge(a,b); used[a] = used[b] = 1,t = 1,leap = 1; while(scanf("%d %d",&a,&b)&&a||b) { if(merge(a,b) == 0) leap = 0; else t--; if(used[a] == 0) t++,used[a] =1; if(used[b] == 0) t++,used[b] = 1; } if(t == 1 && leap) puts("Yes"); else puts("No"); } return 0; }