食物链 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[]的值用向量求,不明白,有懂的给讲解一下!谢谢啦!

原文地址:https://www.cnblogs.com/yaling/p/2956506.html