带权并查集,或者叫做种类并查集,经典题。
http://blog.csdn.net/shuangde800/article/details/7974668
这份代码感觉是坠吼的。
我的代码是暴力分类讨论的,没有用取模的写法,取模的写法更简洁,证明要用到同余的知识,通用性不高,具体可以看上面那份代码。
就并查集每个结点记录与其父节点的关系,并且在路径压缩,以及集合合并的时候进行讨论。
代码风格在程设老师的教育下进行了改变,的确感觉比高中那种代码风格要好点。
#include<cstdio> using namespace std; int fa[50010],rel[50010]; int n,m,ans; int findroot(int x){ if(x==fa[x]){ return x; } int Fa=findroot(fa[x]); if(rel[x]==0 && rel[fa[x]]==0){ rel[x]=0; } else if(rel[x]==0 && rel[fa[x]]==1){ rel[x]=1; } else if(rel[x]==0 && rel[fa[x]]==2){ rel[x]=2; } else if(rel[x]==1 && rel[fa[x]]==0){ rel[x]=1; } else if(rel[x]==1 && rel[fa[x]]==1){ rel[x]=2; } else if(rel[x]==1 && rel[fa[x]]==2){ rel[x]=0; } else if(rel[x]==2 && rel[fa[x]]==0){ rel[x]=2; } else if(rel[x]==2 && rel[fa[x]]==1){ rel[x]=0; } else if(rel[x]==2 && rel[fa[x]]==2){ rel[x]=1; } return fa[x]=Fa; } int main(){ // freopen("poj1182.in","r",stdin); int op,x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ fa[i]=i; } for(int i=1;i<=m;++i){ scanf("%d%d%d",&op,&x,&y); if(x>n || y>n || (op==2 && x==y)){ ++ans; continue; } int f1=findroot(x),f2=findroot(y); if(f1==f2){ if(op==1){ if(rel[x]!=rel[y]){ ++ans; } } else{ if(rel[x]==0 && rel[y]!=2){ ++ans; } else if(rel[x]==1 && rel[y]!=0){ ++ans; } else if(rel[x]==2 && rel[y]!=1){ ++ans; } } } else{ fa[f1]=f2; if(op==1){ if(rel[x]==0 && rel[y]==0){ rel[f1]=0; } else if(rel[x]==0 && rel[y]==1){ rel[f1]=1; } else if(rel[x]==0 && rel[y]==2){ rel[f1]=2; } else if(rel[x]==1 && rel[y]==0){ rel[f1]=2; } else if(rel[x]==1 && rel[y]==1){ rel[f1]=0; } else if(rel[x]==1 && rel[y]==2){ rel[f1]=1; } else if(rel[x]==2 && rel[y]==0){ rel[f1]=1; } else if(rel[x]==2 && rel[y]==1){ rel[f1]=2; } else if(rel[x]==2 && rel[y]==2){ rel[f1]=0; } } else{ if(rel[x]==0 && rel[y]==0){ rel[f1]=1; } else if(rel[x]==0 && rel[y]==1){ rel[f1]=2; } else if(rel[x]==0 && rel[y]==2){ rel[f1]=0; } else if(rel[x]==1 && rel[y]==0){ rel[f1]=0; } else if(rel[x]==1 && rel[y]==1){ rel[f1]=1; } else if(rel[x]==1 && rel[y]==2){ rel[f1]=2; } else if(rel[x]==2 && rel[y]==0){ rel[f1]=2; } else if(rel[x]==2 && rel[y]==1){ rel[f1]=0; } else if(rel[x]==2 && rel[y]==2){ rel[f1]=1; } } } } printf("%d ",ans); return 0; }