HDU 1829 A Bug's Life(基础种类并查集)
链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1829
原题:
Problem DescriptionBackground23 31 22 31 34 21 23 4
Scenario #1:Suspicious bugs found!Scenario #2:No suspicious bugs found!HintHuge input,scanf is recommended.
分析与总结:
做了这题才再次发现自己对并查集的了解真的只是一些皮毛,并查集的很多高级应用我都还不懂,而这题只是种类并查集中最简单的 = =|||。
假设有
1,2
2,3
即1--2--3, 明显相邻的两个不能是同性别的,如果相邻两个是同性的,那么说明就可能是有同性恋存在。
上面假设1是男性,用false来代替,那么按顺序分别是false, true, false
假设 再加个关系3, 1
那么由于1和3已经都有值了,都是false,说明可能有同性恋。
种类并查集的关键在于与结点与根结点的距离, 如果距离是奇数那么性别就和跟结点相反,如果是偶数就和跟结点性别相同。
代码:
#include<cstdio>#define N 2005using namespace std;int f[N],rank[N], n, k;bool flag;inline void init(){ flag=false; for(int i=0; i<=n; ++i) f[i]=i, rank[i]=0;}int find(int x){ if(x==f[x])return f[x]; int t=find(f[x]); rank[x] = (rank[f[x]]+rank[x])&1; f[x]=t; return f[x];}void Union(int x, int y){ int a=find(x), b=find(y); if(a==b){ if(rank[x]==rank[y]) flag=true; return; } f[a]=b; rank[a] = (rank[x]+rank[y]+1)&1;}int main(){ int T,a,b,cas=1; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); init(); for(int i=0; i<k; ++i){ scanf("%d%d",&a,&b); if(flag)continue; Union(a,b); } printf("Scenario #%d:\n",cas++); if(flag)printf("Suspicious bugs found!\n"); else printf("No suspicious bugs found!\n"); printf("\n"); } return 0;}—— 生命的意义,在于赋予它意义。
原创 http://blog.csdn.net/shuangde800 , By D_Double (转载请标明)