poj2492&&hdu1829

链接:点击打开链接

题意:给出一个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;
}
poj2492&&hdu1829_第1张图片

你可能感兴趣的:(poj2492&&hdu1829)