用relaton[]数组保存结点与父节点的关系
同时要考虑两个集合并的时候,在状态压缩时要判断子结点与新的父节点的关系
思路来源:
http://blog.youkuaiyun.com/qq_33901573/article/details/52005905
http://blog.youkuaiyun.com/roney_win/article/details/9408571
#include<iostream>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50000+5;
int p[maxn],r[maxn];//relation
int getParent(int x){
if(p[x]==x) return x;
int xp=getParent(p[x]);
r[x]=(r[x]+r[p[x]])%3;
return p[x]=xp;
}
void merge(int d,int xp,int yp,int x,int y)
{
p[yp]=xp;
r[yp]=(3+(d-1)+r[x]-r[y])%3;
}
int main()
{
int N,K,D,X,Y;
cin>>N>>K;
int wrong=0;
for(int i=1;i<=N;i++) p[i]=i;
while(K--)
{
cin>>D>>X>>Y;
if(X>N||Y>N) wrong++;
else if(D==2&&X==Y) wrong++;
else {
int xp=getParent(X);
int yp=getParent(Y);
if(xp!=yp) merge(D,xp,yp,X,Y);
else
{
if(D==1&&r[X]!=r[Y]) wrong++;
else if(D==2&&((r[Y]-r[X]+3)%3)!=1) wrong++;
}
}
}
cout<<wrong;
return 0;
}