POJ1182 食物链
并查集,relation数组保存当前节点与根节点的关系,0表示当前节点与根节点同类,1当前节点吃根节点,2根节点吃当前节点,关系推导公式可见 poj discuss ,不过由于节点合并方式不一样,所以推导函数有细微的差别。
代码
#include<iostream>
using namespace std;
#define M 50001
int root[M],relation[M];
int findRoot(int x)
{
int t;
if(root[x] != x)
{
t = root[x];
root[x]=findRoot(root[x]);
relation[x] = (relation[x]+relation[t])%3;
}
return root[x];
}
bool IsTrue(int d, int x, int y)
{
int a,b;
a = findRoot(x);
b = findRoot(y);
if(a==b)
return (3 + relation[x] - relation[y])%3==d ? true : false;
else
root[b]=a,relation[b]=(6-d+relation[x]-relation[y])%3;
return true;
}
int main()
{
int i,N,K,d,x,y,ans=0;
scanf("%d %d", &N, &K);
for(i=0;i<=N;i++)root[i]=i,relation[i]=0;
for(i=0;i<K;i++)
{
scanf("%d %d %d", &d, &x, &y);
if(x>N||y>N||(x==y&&d!=1))ans++;
else if(!IsTrue(d-1,x,y))ans++;
}
printf("%d\n", ans);
return 0;
}