http://acm.hdu.edu.cn/showproblem.php?pid=1829
并查集,二分图识别
如果A喜欢B,不能直接判断A,B的性别,但是可以知道,A喜欢的人和B是同性的(一个集合)。
不直接合并A,B所在集合,而间接合并A喜欢的人所在集合 与 B所在集合,使问题得到简化。
建立一个like数组,储存A喜欢的一个人为like[A](任意一个都可以),
1.初始化:
开始让每个人喜欢自己,like[i] = i;
在执行合并操作(3)之前,如果A,B双方中还有喜欢自己的,则调整为喜欢对方,like[A] = B, like[B] = A;
2.查询操作:
如果A和B在一个集合中,则AB属于同性恋
3.合并操作:
把A喜欢的人所在集合(find(like[A]))与 B所在集合(find(B)) 合并
把B喜欢的人所在集合(find(like[B]))与 A所在集合(find(A)) 合并
1 #include <stdio.h> 2 #define N 2013 3 4 int n, m, f[N], l[N]; 5 //f-->father, l-->like 6 7 int find(int x) 8 { 9 return x-f[x]? f[x]=find(f[x]): x; 10 } 11 12 int merge(int x, int y) 13 { 14 int r1, r2;//r-->root 15 r1 = find(x), r2 = find(y); 16 if(r1 != r2) 17 { 18 if(l[x] == x) 19 { 20 l[x] = y; 21 } 22 if(l[y] == y) 23 { 24 l[y] = x; 25 } 26 f[find(l[x])] = r2; 27 f[find(l[y])] = r1; 28 return 0; 29 } 30 return 1; 31 } 32 33 int main() 34 { 35 int t, cases, i, a, b, flag; 36 scanf("%d", &t); 37 for(cases=1; cases<=t; cases++) 38 { 39 scanf("%d%d", &n, &m); 40 for(i=1; i<=n; i++) 41 { 42 f[i] = l[i] = i; 43 } 44 flag = 0; 45 for(i=1; i<=m; i++) 46 { 47 scanf("%d%d", &a, &b); 48 if(!flag && merge(a, b)) 49 { 50 flag = 1; 51 } 52 } 53 printf("Scenario #%d:\n", cases); 54 printf(flag? "S": "No s"); 55 printf("uspicious bugs found!\n\n"); 56 } 57 return 0; 58 }