POJ2492

FIND函数要用到路径压缩的原因是在根节点的一颗子树上,沿着这颗子树的所有子节点都与他的父亲节点互为异性,所以可以直接看成字数上的所有子节点都与祖先节点互为异性。所以用路径压缩。

#include <stdio.h>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
using namespace std;
#define L(x) x<<1
#define R(x) x<<1|1
#define pi actan(-1.0)//常规,误删
#define mem(x,y) memset(x,y,sizeof(x))
#define per(i,n) for(int i=1;i<=n;++i)
#define rep(i,n) for(int i=n;i>=1;--i)
const int max_=2000+10;//更改+10之前的
int pra[max_],n,m,a,b,flag,rank[max_];
void init()
{
    per(i,n)    pra[i]=i;
}
int find(int x)
{
    int tmp,son;
    son=x;
    while(x!=pra[x])//还没有找到根节点
        x=pra[x];//把当前节点改为他的上级
    while(son!=x)//路径压缩
    {
        rank[son]=(rank[son]+rank[pra[son]])%2;
        tmp=pra[son];
        pra[son]=x;
        son=tmp;
    }
    return x;//当前的节点已经是根节点了,于是,返回查询节点的根节点,整个过程不改变树的结构,只负责查询
}
int join(int b1,int b2)//两颗树的合并操作
{
    int x=find(b1);//找到树b1的根节点
    int y=find(b2);//找到树b2的根节点
    if(x==y)
    {
        if((rank[b1]+rank[b2])%2==0)
            return 1;
        else    return 0;
    }
    else
    {
        pra[y]=x;
        rank[y]=(rank[b1]+rank[b2]+1)%2;
    }
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    per(i,t)
    {
        flag=0;//没有同性恋
        mem(rank,0);
        scanf("%d%d",&n,&m);
        init();
        per(j,m)
        {
            scanf("%d%d",&a,&b);
            if(join(a,b))
                flag=1;
        }
        printf("Scenario #%d:\n",i);
        if(flag==0)
            printf("No suspicious bugs found!\n");
        else
            printf("Suspicious bugs found!\n");
        if(i<t)
            printf("\n");
    }
    return 0;
}

本体采用了路径压缩,便于处理rank,是子节点与祖先接待你直接相连,然后从底向上更改rank,这样就只有两层的深度(估计的),之后,只要比较同一层次有没有连接的情况,就可以判断是否矛盾,

猜你喜欢

转载自blog.csdn.net/ivanzn/article/details/81180084