• NOI 2001 食物链 /// 并查集 oj22035


    Description

    动物王国中有三类动物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),输出假话的总数。

    Input

    有多组测试用例。第一行是一个正整数T,表示测试用例的个数。

    每个测试用例的第一行是两个整数N和K,以一个空格分隔。

    接下来K行,每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。

    若D=1,则表示X和Y是同类。

    若D=2,则表示X吃Y。

    Output

    每个测试用例单独输出一行:一个整数,表示假话的数目。

    Sample Input

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

    Sample Output

    3

    使用并查集 

    有三种不同的关系 所以用 +n +2*n 对应不同关系

    若x与y 属同级 合并(x,y)(x+n,y+n)(x+2*n,y+2*n)

    若x与y 为x吃y 合并(x,y+n)(x+n,y+2*n)(x+2*n,y)

    所以 若是y吃x 则 y 与 x+2*n 在同一集合中

    #include <bits/stdc++.h>
    using namespace std;
    int n,k,root[150005];
    int Find(int x)
    {
        int man=x;
        while(root[man]!=man)
            man=root[man];
        int oman=x;
        while(root[oman]!=man)
        {
            int tmp=root[oman];
            root[oman]=man;
            oman=tmp;
        }
        return man;
    }
    void unite(int x,int y)
    {
        int xman=Find(x),yman=Find(y);
        if(xman!=yman) root[xman]=yman;
    }
    bool same(int x,int y)
    {
        return Find(x)==Find(y);
    }
    int main()
    {
        int t;
        while(~scanf("%d",&t))
        {
            while(t--)
            {
                scanf("%d%d",&n,&k);
                for(int i=1;i<=n*3;i++)
                    root[i]=i;
                int ans=0;
                while(k--)
                {
                    int d,x,y; scanf("%d%d%d",&d,&x,&y);
                    if(x<1 || x>n || y<1 || y>n)
                    {   ans++; continue;    }
                    if(d==1)
                    { 
                        if(same(x,y+n) || same(x,y+n*2)) ans++;
                        else unite(x,y),unite(x+n,y+n),unite(x+n*2,y+n*2);
                    }
                    else
                    {
                        if(same(x,y) || same(x,y+n*2)) ans++;
                        else unite(x,y+n),unite(x+n,y+n*2),unite(x+n*2,y);
                    }
                }
                printf("%d
    ",ans);
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    mybatis下使用log4j打印sql语句和执行结果
    chrome不支持embed标签解决方案
    在java中String类为什么要设计成final
    代理模式
    注解(二)模拟实体到数据库表字段的映射
    注解(一)
    python-redistest
    Agens层次聚类
    KNN近邻算法
    K-means聚类算法
  • 原文地址:https://www.cnblogs.com/zquzjx/p/8893868.html
Copyright © 2020-2023  润新知