不想多说什么了,这题虐我不浅,还是看完别人的解题报告的情况下。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int father[50001],relative[100001];
int n;
int find_ant(int c){
if(father[c]!=c){
int t=find_ant(father[c]); //这一句和下一句不能颠倒,relative[]必须出现在find_ant()后,也就是说relative[]是在递归的回溯过程中建立的,这样才能保证relative[]对应的祖先节点是正确的。只有在祖先节点确定的情况才能计算relative[]。而relative[]出现在find_ant()前面时,先建立了relative[]和当前的祖先节点(并非最终确定的祖先节点),随后祖先节点又在递归中被改变,relative[]就不正确了。罗嗦了大半天,就一句,relative[]的建立一定出现在find_ant()之后。
relative[c]=(relative[c]+relative[father[c]])%3;
father[c]=t;
}
return father[c];
}
bool _union(int x,int y,int r){
int px=find_ant(x);
int py=find_ant(y);
if(x>n||y>n) return true;
if(px==py){
if(relative[x]==relative[y]&&r==1) return false;
if((relative[x]-relative[y]+3)%3==2&&r==2)
return false;
return true;
}
relative[py]=(3-relative[y]+r-1+relative[x])%3;
father[py]=px;
return false;
}
int main(){
int k;
int i;
int x,y,g;
int res=0;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++){
father[i]=i;
relative[i]=0;
}
while(k--){
scanf("%d%d%d",&g,&x,&y);
if(_union(x,y,g))
res++;
}
printf("%d\n",res);
return 0;
}