【codevs1074】食物链

这个题……表示在伟大神犇lxt的指引下终于明白了qwq,lxt太神了orz

http://www.studyai.com/article/0d732f3e 丢一波神犇的博客

这个题普通的并查集是难以维护的(就算可以也是要开好几倍空间的扩展域并查集),所以这里主要写加权并查集

我们用0表示二者同类,1表示x吃y(它吃父亲),2表示y吃x(它被父亲吃) ,合并的时候需要在原来的关系值上加上相应的权值,利用向量加减的思想,我们可以比较容易的理解这个题(虽然它能应用的范围并不广泛)

#include<iostream>
#include<cstdio>
using namespace std;
int n,k,fa[50050],v[50050],z,x,y,ans;
int find(int x)
{
    if(fa[x]==x)
        return x;
    int f=fa[x];
    fa[x]=find(fa[x]),v[x]=(v[x]+v[f]+3)%3;//因为x现在指向祖宗,f指向祖宗,x原来指向f,可以利用向量运算 
    return fa[x];
}
//用0表示二者同类,1表示x吃y(它吃父亲),2表示y吃x(它被父亲吃) 
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=k;i++)
    {
        scanf("%d%d%d",&z,&x,&y);
        if(x>n||y>n)//特判 
            ans++;
        else if(x==y&&z==2)
            ans++;
        else
        {
            int qwq=find(x),qaq=find(y);
            if(qwq!=qaq)
            {
                if(z==1)//如果x与y是同类,那么说x祖宗的关系会受到y其祖宗对y的关系的影响,+3是为了防止出现负数,实际上应是+3+0 
                    fa[qwq]=qaq,v[qwq]=(v[y]-v[x]+3)%3;
                else//如果x吃y,那么说它祖宗到y关系+1 
                    fa[qwq]=qaq,v[qwq]=(v[y]-v[x]+4)%3;
            }
            else
            {
                if(z==2&&v[x]%3!=(v[y]+1)%3)//如果x吃y但是v[x]不等于v[y]+1(因为v[x]=(v[y]+1)%3)
                    ans++;
                else if(z==1&&v[x]%3!=v[y]%3)//如果x与y是同类但是v[x]!=v[y](显而易见) 
                    ans++;
            }
        }
    }
    printf("%d",ans);
}

 

posted @ 2017-10-27 08:51  那一抹落日的橙  阅读(180)  评论(0编辑  收藏  举报