题目链接:点击打开链接
题目大意:
有n个动物,关于他们的食物链关系有K种说法,要判断这K种说法中假的
说法个数。
第一次知道并查集怎么解种类关系问题。
参考博客:点击打开链接
但是奇葩的是这题多组数据就wa,只有单组数据能过!!!
值得注意的是,
1、find函数必须用递归写,因为路径压缩时更新每个点到新的父亲的关系要从最后面
推到当前节点来。
错误写法:
int find(int x)
{
int r=x;
while(fa[r]!=r)
r=fa[r];
int u=x;
while(fa[u]!=r)
{
int t=fa[u];
re[u]=(re[u]+re[t])%3;
fa[u]=r;
u=t;
}
return r;
}
2、合并两个集合的时候是修改fx或者fy的re[],而不是x或者y的re[]。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int fa[50010];
int re[50010];
int n;
void init()
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
re[i]=0;
}
}
int find(int x)
{
if( x != fa[x])
{
int t=fa[x];
fa[x]=find(fa[x]);
re[x]=(re[x] + re[t])%3;
}
return fa[x];
}
void Union(int x,int y,int d)
{
int fx=find(x);
int fy=find(y);
fa[fx]=fy;
re[fx]=(re[y]+d+3-re[x])%3;
}
int main()
{
int m,ans,a,b,c;
//while(scanf("%d%d",&n,&m)!=EOF)
//{
scanf("%d%d",&n,&m);
init();
ans=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(b>n || c>n)
{
ans++;
continue;
}
if(a==2 && b==c)
{
ans++;
continue;
}
int fx=find(b);
int fy=find(c);
if(fx==fy)
{
if((re[b]-re[c]+3)%3 != a-1)
ans++;
}
else
Union(b,c,a-1);
}
printf("%d\n",ans);
//}
return 0;
}