食物链 noj207
#include<stdio.h>
int fa[50005]={0};
int rank[50005]={0};
int n;
void initial()
{
for(int i=1;i<=n;i++)
{
fa[i]=i; rank[i]=0;
}
}
int getfather(int x)
{
if(x==fa[x]) return x;
int oldfa = fa[x];
fa[x]=getfather(fa[x]);
rank[x]=(rank[x]+rank[oldfa])%3; //用向量的形式很快就可以看出来
return fa[x];
}
void unionset(int r,int x,int y)
{
int fx,fy;
fx=getfather(x); fy=getfather(y);
if(fx==fy) return;
fa[fx]=fy;
rank[fx]=(rank[y]+r-rank[x]+3)%3; // 这里同样可以用向量来推公式。另外需要注意的是,这里只更新了fx的rank值,而fx的儿子的rank值都没有更新会不会有问题。其实不碍事,由于我们每次输入一组数据我们都对x和y进行了getfather的操作(x>n || y>n ……)的除外。在执行getfather的操作时,在回溯的过程中就会把fx的儿子的rank值都更新了。
return ;
}
int istrue(int d,int x,int y)
{
int fx,fy,r;
if(x>n || y>n || ((x==y)&&(d==2)) )
return 0;
fx=getfather(x); fy=getfather(y);
if(fx!=fy) return 1;
else
{
if(rank[x]==((d-1)+rank[y])%3) return 1; // 这个公式可以用向量来推:如果( f(x,y) + f(y,father[y]))% 3 == f(x,father[x]) 则是正确的,否则是错的。这个形式可以用向量来表示,就是判断这个向量加法对不对 x--->y + y---> fx(fy) 是否等于 x--->fx(fy)
else return 0;
}
}
int main()
{
int k,i,x,y,d; int ans=0;
scanf("%d%d",&n,&k);
initial();
for(i=1;i<=k;i++)
{
scanf("%d%d%d",&d,&x,&y);
if( !istrue(d,x,y) )
ans++;
else
unionset(d-1,x,y);
}
printf("%d\n",ans);
return 0;
}
对于rank[]的值用向量求,不明白,有懂的给讲解一下!谢谢啦!
浙公网安备 33010602011771号