输入
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数D,X,Y,两数之间用一个空格隔开,其中 D 表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
输出
样例输入
100 7100 7
1 101 1 假话1 5 5 真话
经典的关系类并查集,理解这类东西花了几个星期,自己还是太笨了。好吧其实关键就是,一个集合内的元素都会有一个偏移量,是相对于老祖宗而言的相对关系,只要懂得这点,合并两个集合时修改相对距离也就易如反掌了。
#include<cstdio> #include<iostream> using namespace std; int n,m,u,v,x,y,z,ans; int f[50005],dis[50005]; int get(int x) { if(f[x]==x) return x; int t=f[x]; f[x]=get(f[x]); dis[x]=(dis[x]+dis[t])%3; return f[x]; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { scanf("%d%d%d",&z,&x,&y); if(x>n||y>n) { ans++; continue; } if(z==1) { u=get(x); v=get(y); if(u==v) { if(dis[x]!=dis[y]) ans++; } else { f[u]=v; if(dis[x]!=dis[y]) dis[u]=(dis[y]-dis[x]+3)%3; } } else { if(x==y) { ans++; continue; } u=get(x); v=get(y); if(u==v) { if((dis[x]-dis[y]+3)%3!=2) ans++; } else { f[u]=v; if((dis[x]-dis[y]+3)%3!=2) { int l=(dis[x]-dis[y]+3)%3; dis[u]=2-l; } } } } cout<<ans<<endl; return 0; }