题目要求 : 判断所给的图是否连同并且是否存在环
并查集 做这一个题 实在是再好不过了 , 是否连同可以 看有几个顶点 , 是否存在环 , 看看 是否有一条边的 两个定点 的祖先节点 是一个点 . 下面附上渣渣代码
1 #include<stdio.h>
2 #include<string.h>
3 #include<math.h>
4 #include<iostream>
5 #include<algorithm>
6 #include<queue>
7 #include<vector>
8 #include<set>
9 #include<stack>
10 #include<string>
11 #include<sstream>
12 #include<map>
13 #include<cctype>
14 using namespace std;
15 int father[100005],visited[100005],sum,flag;
16 int find(int x) // 做了时间上的优化 ,但是 在空间复杂度上比较高
17 {
18 if(x!=father[x])
19 father[x]=find(father[x]);
20 sum++;
21 return father[x];
22 }
23 void merge(int x,int y) // 做了时间复杂度上的优化 让并查集的 深度尽量 浅
24 {
25 int sum1,sum2;
26 sum=0;
27 x=find(x);
28 sum1=sum; // x 的深度
29 sum=0;
30 y=find(y);
31 sum2=sum; // y 的深度
32 if(x!=y)
33 {
34 if(sum1>sum2)
35 father[y]=x;
36 else
37 father[x]=y;
38 }
39 else
40 flag=1; // 同一条边 的 两个父节点相同 , 则成环了
41 }
42 int main() // 所有的 房间应该还是 连通的
43 {
44 int n,m;
45 while(scanf("%d%d",&n,&m)) // 不能 存在 环
46 {
47 flag=0;
48 if(n==m&&n==-1)
49 break;
50 if(n==m&&n==0)
51 {
52 printf("Yes
");
53 continue;
54 }
55 for(int i=0;i<100005;i++)
56 {
57 father[i]=i; // i 的 爸爸 还是 i
58 visited[i]=0; // 初始化 访问标记
59 }
60 visited[n]=visited[m]=1; // 这两个点 标记以访问
61 merge(n,m); // 这个两个点 先构树
62 while(scanf("%d%d",&n,&m))
63 {
64 if(n==m&&n==0)
65 break;
66 merge(n,m);
67 visited[n]=visited[m]=1;
68 }
69 int count1=0;
70 for(int i=0;i<100005;i++)
71 {
72 if(visited[i]&&father[i]==i)
73 count1++;
74 if(count1>1)
75 {
76 flag=1;
77 break;
78 }
79 }
80 if(flag)
81 printf("No
");
82 else
83 printf("Yes
");
84 }
85 return 0;
86 }