链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1829
原题:
2 3 3 1 2 2 3 1 3 4 2 1 2 3 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 2005 using 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 (转载请标明)