链接:点击打开链接
题意:给出一个T代表几组数据,给出一个m一个n,代表人的编号由1~m,n条命令,每条命令由两个数值组成,代表这两个人性别不同,问所有命令是否符合逻辑
例如:给出数据为1||3 3||1 2||1 3||2 3,表示1,2性别不同,1,3性别不同,因此可以推断出2,3性别一定相同,但是由给出了2,3因此不符合逻辑
代码:
#include <iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int f[10005],dis[10005]; //dis数组代表该节点与父节点的关系,1代表与父节点性别不同,反之即为0
int found(int x){
int t;
if(f[x]!=x){
t=found(f[x]);
dis[x]=(dis[x]+dis[f[x]])%2; //根据儿子与父亲的关系和父亲与爷爷的关系推出儿子与爷爷的关系
f[x]=t; //可以自己枚举一下试一下
}
return f[x];
}
int main(){
int i,k,t,n,m,a,b,flag,temp,temp1;
scanf("%d",&t);
for(k=1;k<=t;k++){
flag=1;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
f[i]=i;
dis[i]=0;
} //形成的数最多由根节点向下延展两成,因为并查集的原则就是根节点
for(i=1;i<=m;i++){ //相连,因此不会延展超过两成
scanf("%d%d",&a,&b);
temp=found(a);temp1=found(b);
if(!flag) //如果已经不符合逻辑就不用继续找了
continue;
if(temp==temp1){ //当根节点相同时,判断dis数组的值是否相同,
if(dis[a]==dis[b]) //这个可以自己画一个树看一下
flag=0;
}
else{
f[temp1]=temp; //当节点不同时将两个点所属的根节点相连,注意这是候的dis[a]代表的是a与根节点的关系,
dis[temp1]=(dis[a]+1-dis[b])%2; //dis[b]代表的是b与根节点的关系,这是因为我们开头的每一次都找了a,b的根节点,在found
} //函数中通过回溯更新了dis数组,之后我们将b连到a上,因此a作为b的父节点,b对a的关系一定
} //1,因为a,b是性别不同的,然后通过向量加减求出两个根节点的关系
if(!flag){
printf("Scenario #%d:\n",k);
printf("Suspicious bugs found!\n\n");
}
else{
printf("Scenario #%d:\n",k);
printf("No suspicious bugs found!\n\n");
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/stay_accept/article/details/47395935