hdu1829(简单带权并查集)

虽然是简单种类带权并查集,但是还是想了很久啊。。。

题意:Bug有两种性别,异性之间才交往, 让你根据数据判断是否存在同性恋,输入有 t 组数据,每组数据给出bug数量n, 和关系数m, 以下m行给出相交往的一对Bug编号 a, b。只需要判断有没有,按题目要求输出。这题有点坑的地方在于输出上多了一行空行,不PE都没注意到。

思路:因为不知道性别,所以要通过建立关系加以判断。这个关系呢通过一个rk数组,rk[i]表示i到从属的根节点的关系,不断读入数据的时候不断创建这样的关系,使用mix函数,如果两个x,y的根节点root已经是同一个集合里的了,因为rk[x],rk[y]是指在root下的相对关系0/1,所以可以直接比较rk[x]==rk[y]判断是否满足关系。否则如果两个根不在一起,那就通过创建两个根的关系来mix,修改公式:fa[fx]=fy;rk[fx]=(f[y]-f[x]+1)%2;用向量思想推一推就出来了。


代码:

#include<cstdio>
#include<algorithm>
using namespace std;
using namespace std;
const int maxn=100006;
int fa[maxn];
int rk[maxn];
int flag;
void init(int n){
 flag=0;
 for(int i=0;i<=n;i++){
  fa[i]=i;
  rk[i]=0;
 }
}
int find(int x){
 if(x==fa[x])return x;
 int f=find(fa[x]);
 rk[x]=(rk[x]+rk[fa[x]])%2;
 return fa[x]=f;
}
void mix(int x,int y){
 int fx=find(x);
 int fy=find(y);
 if(fx==fy){
  flag=(rk[x]==rk[y]);
 }else{
  fa[fx]=fy;
  rk[fx]=(-rk[x]+1+rk[y])&1;
 }
}
int main(){
 int t;
 int q=1;
 scanf("%d",&t);
 while(t--){
  int n,k;
  scanf("%d%d",&n,&k);
  init(n);
  while(k--){
   int a,b;
   scanf("%d%d",&a,&b);
   if(flag)continue;
   mix(a,b);
  }
  if(flag)
   printf("Scenario #%d:\nSuspicious bugs found!\n\n",q++);
  else
   printf("Scenario #%d:\nNo suspicious bugs found!\n\n",q++);
 }
}

猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/80488118