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