这题的拓展域可变为
将X拆为 X是A族、B族、C族三个点
根据吃或者同族关系互相推导
例如 1 x y 就将(xA,yA),(xB,yB),(xC,yC)连边表示可互相推导
当可以推导出X同时属于两个种族时则是假话,具体细节请见代码。
(略(shi)显(fen)凌乱)
#include<iostream>
#include<cstdio>
#include<tr1/unordered_map>
#include<set>
#include<cmath>
#include<queue>
#include<algorithm>
#include<stack>
using namespace std;
using namespace tr1;
typedef long long ll;
const int N=50005,inf=0x3f3f3f3f;
int n,k,cnt,fa[3*N],ans;
int find(int x)
{
if(fa[x]!=x)return fa[x]=find(fa[x]);
return x;
}
int main(){
// freopen("123.txt","r",stdin);
scanf("%d%d",&n,&k);
for(int i=0;i<=3*n;i++)fa[i]=i;
for(int i=1;i<=k;i++)
{
int x,y,key;
scanf("%d%d%d",&key,&x,&y);
if((x==y&&key==2)||x>n||y>n){ans++;continue;}
if(key==1)
{
if((fa[find(x)]!=find(y)&&fa[find(x)]%n==find(y)%n) || (fa[find(x+n)]!=find(y+n)&&fa[find(x+n)]%n==find(y+n)%n) ||(fa[find(x+2*n)]!=find(y+2*n) &&fa[find(x+2*n)]%n==find(y+2*n)%n) ){ans++;continue;}
fa[find(x)]=find(y);
fa[find(x+n)]=find(y+n);
fa[find(x+2*n)]=find(y+2*n);
}
else
{
if((fa[find(x+n)]!=find(y)&&fa[find(x+n)]%n==find(y)%n)||(fa[find(x+2*n)]!=find(y+n)&&fa[find(x+2*n)]%n==find(y+n)%n) || (fa[find(x)]!=find(y+2*n)&&fa[find(x)]%n==find(y+2*n)%n) ){ans++;continue;}
fa[find(x+n)]=find(y);
fa[find(x+2*n)]=find(y+n);
fa[find(x)]=find(y+2*n);
}
}
cout<<ans;
}
额额额其实判断只需要判断一个就行了 不需要自身 吃 被吃 三个都判断
生怕我能看懂
窝也泽阳做的OvO
棒~
加油!