标签:
Description
Input
Output
Sample Input
2 3 3 1 2 2 3 1 3 4 2 1 2 3 4
Sample Output
Scenario #1: Suspicious bugs found! Scenario #2: No suspicious bugs found!
Hint
说起来并查集真是一个好东西
就 我目前知道的而言 1.判断是否成环2.计算环的个数3.计算集合的个数 其实都是一个道理 就是看你怎么想
当然了 并查集还有按秩合并 压缩路径
怎么解释按秩合并呢 其实说白了就是按照两个人的rank等级建立关系
int x=find(a); int y=find(b); if(rank[x]>rank[y])//按秩合并 fa[y]=x; else { fa[x]=y; if(rank[x]==rank[y]) rank[y]++; }压缩路径(当看到数组特别大时 慎重啊 爆栈 如hdu1272)
压缩路径的意思就是在查找的过程中 使当前节点的值更新,直到根节点 便于下次查找节省时间
int find(int x) { if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; }
int find(int x) 13.{ 14. while(fa[x]!=x) 15. x=fa[x]; 16. return fa[x]; 17.}
这道题起初真的没理解啊。。直接并查集 结果错了 听到队友说好像要分男女 也想了一个方法 就是判断
这对关系中某个人有没有出现过 一个出现另外一个就好判断了 后来想了一组测试数组 1 2 3 4 1 3 。。。我想错了
最后看的别人的代码 理解了
思路: 我们可以把男 女分为两个集合 如果出现的新的关系里面并查集出现了环 那么 就说明这两个人都是男 或者都是女
#include <stdio.h> #include <string.h> int fa[2005]; int rela[2005]; bool bugs; void init(int n) { for(int i=1;i<=n;i++) fa[i]=i,rela[i]=0; } int find(int x) { if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } void uni(int a,int b) { int aa=find(a); int bb=find(b); if(aa!=bb) fa[aa]=bb; } int main() { int ncase; int t=1; scanf("%d",&ncase); while(ncase--) { int n,m; scanf("%d %d",&n,&m); init(n); bugs=false; for(int i=0;i<m;i++) { int x,y; scanf("%d %d",&x,&y); if(!bugs) { int xx=find(x); int yy=find(y); if(xx==yy) bugs=true; if(rela[x]) uni(rela[x],y); else rela[x]=y; if(rela[y]) uni(rela[y],x); else rela[y]=x; } } printf("Scenario #%d:\n",t++); if(bugs) puts("Suspicious bugs found!\n"); else puts("No suspicious bugs found!\n"); } return 0; }
标签:
原文地址:http://blog.csdn.net/su20145104009/article/details/51441044