题目连接:http://poj.org/problem?id=2492
大意大概解释给你一个t代表多少个case,然后有n个虫子,m个谁喜欢谁,这种虫子跟咱们一个货色只有两种性别,男的,或者是母的,然后就是让你算算有没有高搞基或者是百合。
大体思路就是用并查集,然后用一个数组算这个节点到根节点的长度,然后看相同具有相同祖先的是不是有相同的长度%2.
//昨天心情不大好特别想回家,一下午再看这道题晚上偷懒一直在看视频。。。 //一开始觉得无非就是查看这个节点的深度,然后一直打算用h去计算,后不断地wa然后就想了想h是指该节点到最底下的那个高度,然后就开始用了另一个数组num去储存离跟节点的长度,也就是一直在问冯刚队长的偏移量。另外多说一句题外话昨天赵队长然我很难堪啊= =。。。
View Code
#include <stdio.h> #include <stdlib.h> int set[2001],num[2001],h[2001]; int find(int x)//之前我的并查集的find一直是在用循环来需找根节点,这道题要用递归,因为这个题的find 用while去写的话。。。我不会= =。。。 { if(x!=set[x]) { int y = set[x]; set[x] = find(set[x]); num[x] += num[y]; } return set[x];//记得一定是要返回set[x]因为返回x的话这里的声明是的原值。与while 不一样。 } void merge(int x, int y) { int a = find(x); int b = find(y); if(a!= b) { if(h[a]>h[b]) { set[b] = a; num[b] = (num[x]-num[y]+1);//因为h[a]的树比较高,所以这里用num[x]-num[y],事实上如果这个数很大的话我建议加上%2,因为加上%2结果不会改变~; } else { set[a] = b; num[a] = (num[y]-num[x]+1); if(h[a] == h[b]) h[b]++; } } } int main() { int i, j, m, n,t,a,b,g; long k; k = 0; scanf("%d", &t); while(t--) { k++; scanf("%d%d", &n, &m); int leap = 1; for(i = 1 ; i <= n ; i++) set[i] = i,h[i] = 0,num[i] = 0; for(i = 1 ; i <= m ; i++) { scanf("%d%d", &a,&b); if(a!=b) merge(a,b); if(find(a) == find(b)&&num[a]%2==num[b]%2)//同一个根节点跟根节点的距离%2相同 leap = 0; } printf("Scenario #%ld:\n",k); if(leap) printf("No suspicious bugs found!\n"); else printf("Suspicious bugs found!\n"); if(t!=0) printf("\n"); } return 0; }