• 带权并查集复习——食物链


        动物王国中有三类动物  A,B,C,这三类动物的食物链构成了有趣的环形。A吃B,B吃C,C吃A。         现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。         有人用两种说法对这N个动物所构成的食物链关系进行描述:         第一种说法是“1  X  Y”,表示X和Y是同类。         第二种说法是“2  X  Y”,表示X吃Y。         此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。         1)  当前的话与前面的某些真的话冲突,就是假话;         2)  当前的话中X或Y比N大,就是假话;         3)  当前的话表示X吃X,就是假话。         你的任务是根据给定的N(1< =N< =50,000)和K句话(0< =K< =100,000),输出假话的总数。

    输入

            第一行是两个整数N和K,以一个空格分隔。         以下K行每行是三个正整数D,X,Y,两数之间用一个空格隔开,其中  D  表示说法的种类。         若D=1,则表示X和Y是同类。         若D=2,则表示X吃Y。

    输出

            只有一个整数,表示假话的数目。

    样例输入

    100 7
    1 101 1
    2 1 2
    2 2 3
    2 3 3 
    1 1 3
    2 3 1
    1 5 5
    
    

    样例输出

    3
    

    提示

    100 7

    1 101 1    假话 

    2 1 2      真话 

    2 2 3      真话 

    2 3 3      假话 

    1 1 3      假话 

    2 3 1      真话 

    1 5 5      真话 

     很老的一道题,与根节点的关系:1表示吃祖先,2表示被祖先吃,0表示与祖先同类。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int ans,n,k,rep[1000005],rel[1000005];
    int getrep(int x)
    {
        if(x==rep[x]) return x;
        int fa=rep[x];
        rep[x]=getrep(rep[x]);
        rel[x]=(rel[x]+rel[fa]+3)%3;
        return rep[x];
    }
    void anticipation()
    {
        scanf("%d %d",&n,&k);
        for(int i=1;i<=n;i++)
        rep[i]=i,rel[i]=0;
    }
    void did()
    {
        for(int i=1;i<=k;i++)
        {
            //for(int j=1;j<=n;j++)
            //printf("j:%d rep[j]:%d rel[j]:%d
    ",j,rep[j],rel[j]);
            int pattern,x,y;
            scanf("%d %d %d",&pattern,&x,&y);
            if(x>n||y>n||(x==y)&&(pattern==2))
            {
                ans++;
                //cout<<"False"<<endl;
                continue;
            }
            if(x==y)
            {
            //    cout<<"True"<<endl;
                continue;
            }
            int fax=getrep(x),fay=getrep(y);
            if(fax==fay)
            {
                if((rel[x]-rel[y]+3)%3!=pattern-1) 
                {
                    ans++;
                    //cout<<"False"<<endl;
                    continue;
                }
            //    cout<<"True"<<endl;
                continue;
            }else
            {
                //cout<<"True"<<endl;
                rep[fax]=fay;
                rel[fax]=(rel[y]-rel[x]+pattern+2)%3;
            }
        }
        cout<<ans<<endl;
    }
    int main()
    {
        anticipation();
        did();
    }
  • 相关阅读:
    【转载】大型系统中使用JMS优化技巧
    【原创】JMS发布者订阅者【异步接收消息】
    【原创】JMS生产者和消费者【PTP异步接收消息】
    泛型
    For-Each循环
    策略模式(Strategy)
    Sort--快速排序
    Serach
    Sort--冒泡排序
    数值交换
  • 原文地址:https://www.cnblogs.com/dancer16/p/7235974.html
Copyright © 2020-2023  润新知