#include<stdio.h> int fa[50005]={0}; int rank[50005]={0}; int n; void initial() { for(int i=1;i<=n;i++) { fa[i]=i; rank[i]=0; } } int getfather(int x) { if(x==fa[x]) return x; int oldfa = fa[x]; fa[x]=getfather(fa[x]); rank[x]=(rank[x]+rank[oldfa])%3; //用向量的形式很快就可以看出来 return fa[x]; } void unionset(int r,int x,int y) { int fx,fy; fx=getfather(x); fy=getfather(y); if(fx==fy) return; fa[fx]=fy; rank[fx]=(rank[y]+r-rank[x]+3)%3; // 这里同样可以用向量来推公式。另外需要注意的是,这里只更新了fx的rank值,而fx的儿子的rank值都没有更新会不会有问题。其实不碍事,由于我们每次输入一组数据我们都对x和y进行了getfather的操作(x>n || y>n ……)的除外。在执行getfather的操作时,在回溯的过程中就会把fx的儿子的rank值都更新了。 return ; } int istrue(int d,int x,int y) { int fx,fy,r; if(x>n || y>n || ((x==y)&&(d==2)) ) return 0; fx=getfather(x); fy=getfather(y); if(fx!=fy) return 1; else { if(rank[x]==((d-1)+rank[y])%3) return 1; // 这个公式可以用向量来推:如果( f(x,y) + f(y,father[y]))% 3 == f(x,father[x]) 则是正确的,否则是错的。这个形式可以用向量来表示,就是判断这个向量加法对不对 x--->y + y---> fx(fy) 是否等于 x--->fx(fy) else return 0; } } int main() { int k,i,x,y,d; int ans=0; scanf("%d%d",&n,&k); initial(); for(i=1;i<=k;i++) { scanf("%d%d%d",&d,&x,&y); if( !istrue(d,x,y) ) ans++; else unionset(d-1,x,y); } printf("%d\n",ans); return 0; }
对于rank[]的值用向量求,不明白,有懂的给讲解一下!谢谢啦!