题目链接添加链接描述
题意:中文题不表
解题思路:太经典了,说实话其中的向量偏移的思想减少了好多好多的代码量,不然可能需要使用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;
}