题目链接添加链接描述 题意:中文题不表 解题思路:太经典了,说实话其中的向量偏移的思想减少了好多好多的代码量,不然可能需要使用16个if来判断,实际上,其中的findx函数使用的思想就是同向直接相加的感觉。 很多博文写的很好 代码参考博客 百度推荐第一条博客 向量偏移,再加上递归加权的思想。有点菜,不过加油。
#include<stdio.h> using namespace std; const int maxn = 5e4+9; int fa[maxn],d[maxn]; int n,k; int r[maxn]; int findx(int x) { if(fa[x]==x) return x; else{ int temp=findx(fa[x]); r[x]=(r[x]+r[fa[x]])%3; fa[x]=temp; return fa[x]; // return fa[x]=findx(fa[x]); } } int Union(int op,int x,int y) { int root1=findx(x); int root2=findx(y); if(root1==root2) { if((r[x]-r[y]+3)%3==op-1)return 0; return 1; } fa[root1]=root2; r[root1]=(r[y]-r[x]+op-1+3)%3;///这是网上大牛的方法,巨牛批 ///采用什么向量偏移的方法,我巨服,但是这样的算法思维太过精妙 ///我以后在做类似题目的时候不知道能不能想出来,先学习下,再看看 ///我的基础算法就是if判断 // if(op==1) // { // if(r[x]==1&&r[y]==2)///x吃祖先,y被吃,两人又是同类 // { // r[root1]=2; // } // else if(r[x]==1&&r[y]==1){ // r[root1]=0; // } // else if(r[x]==2) // } return 0; } int sum; int main() { scanf("%d%d",&n,&k); int sum=0; for(int i=1;i<=n;i++) { fa[i]=i,r[i]=0; } for(int i=1;i<=k;i++) { int op,x,y; scanf("%d%d%d",&op,&x,&y); if(op==2&&x==y) { sum++; continue; } if(x>n||y>n) { sum++; continue; } sum+=Union(op,x,y); } printf("%d\n",sum); return 0; }