Uva(10158)

这题真的是并查集的经典题目= =

题意是给出n个人,然后给出若干的操作

1表示让a,b成为朋友,若与前面的朋友敌人关系相矛盾,输出-1

2表示让a,b成为敌人,若与前面的朋友敌人关系矛盾输出-1

3判断a,b是否是朋友,是输出1,不是输出0

4判断a,b是否是敌人,是的话输出1,不是的话输出-1

首先ab朋友关系部成立是他们刚好属于敌对的阵营。同理,a,b的敌对关系不成立的条件是他们属于同一个阵营

#include<stdio.h>
#include<string.h> 
#include<iostream>
#include<algorithm>
using  namespace std;
const int N=10100;
int p[N],q[N],pu,pv,qu,qv;
int find(int x)
{
    return p[x]==x?x:find(p[x]);
}
void fun1()
{
    if(pu==qv&&pv==qu)//a,b属于敌对阵营
    {
        printf("-1
");
    }
    else
    {
        if(qu==-1&&qv==-1)//a,b,没有敌人
        p[pu]=pv;合并关系
        else if(qu==-1)//a没有敌人
        p[pu]=pv;
        else if(qv==-1)//b没有敌人
        p[pv]=pu;
        else//a,b有敌人,但不是敌对阵营,要合并a,b的敌人让他们变成朋友
        {
             p[pu]=pv;
             p[qu]=qv;
        }
    }
}
void fun2()
{
    if(pu==pv)//a,b属于同一个阵营,不符合要求
    {
        printf("-1
");
    } 
    else
    {
        q[pu]=pv;//把a,b分别合并在他们的敌对阵营
        q[pv]=pu;
        if(qu!=-1)
        p[qu]=pv;
        if(qv!=-1)
        p[qv]=pu; //把a,b的敌人合并成朋友关系
    }
}
void fun3()
{
    if(pu==pv)
    printf("1
");
    else
    printf("0
"); 
}
void fun4()
{
    if(pu==qv&&pv==qu)
    printf("1
");
    else
    printf("0
");
}
int main()
{
    int n;
    scanf("%d",&n); 
        for(int i=0;i<=n;i++)
        {
            p[i]=i;
            q[i]=-1;
        }
       int a,b,c;
       while(scanf("%d %d %d",&c,&a,&b)!=EOF)
       {
             if(!a&&!b&&!c)
             break;
             pu=find(a);
             pv=find(b);
             qu=q[pu];
             if(qu!=-1)
             qu=find(qu);
             qv=q[pv];
             if(qv!=-1)
             qv=find(qv);
             if(c==1)
          fun1();
             else if(c==2)
             fun2();
             else if(c==3)
             fun3();
             else
             fun4(); 
       }
    return 0;
}
 
原文地址:https://www.cnblogs.com/NaCl/p/4928391.html