• 并查集(经典)


    一万只草泥马经过,经典的花了我特么一个礼拜

    题目:https://vjudge.net/problem/POJ-1182

    食物链

    动物王国中有三类动物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
    第一行是两个整数N和K,以一个空格分隔。 
    以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 
    若D=1,则表示X和Y是同类。 
    若D=2,则表示X吃Y。
    Output
    只有一个整数,表示假话的数目。
    Sample Input
    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
    题意:
    A B C三种动物 三种关系  A吃B,B吃C,C吃A;求有多少种错误关系
    题解:
    http://blog.csdn.net/ltyqljhwcm/article/details/52347574
    (大佬的题解还是跟清晰)
    代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<algorithm>
    #include<map>
    #define maxn 100005
    using namespace std;
    int fa[maxn];
    int n,m;
    void init()
    {
        for(int i=1;i<=n*3;i++)
        {
            fa[i]=i;
        }
    }
    int find(int x)
    {
        if(x==fa[x])return x;
        else return fa[x]=find(fa[x]);
    
    }
    void unit(int x,int y)
    {
        x=find(x);
        y=find(y);
        if(x==y)return ;
        else  fa[y]=x;
        return ;
    }
    bool same(int x,int y)
    {
        return find(x)==find(y);
    }
    int main()
    {
        cin>>n>>m;
        init();
        int sum=0;
        for(int i=0;i<m;i++)
        {
            int x,y,z;
            cin>>z>>x>>y;
            if(x>n||y>n)sum++;
            else if(z==2&&x==y)sum++;
            else  {
                if(z==1){
                    if(same(x,y+n)||same(x,y+2*n))sum++;
                else {
                    unit(x,y);
                    unit(x+n,y+n);
                    unit(x+2*n,y+2*n);
                }
                }
                else  {
                    if(same(x,y)||same(x,y+2*n))sum++;
                    else {
                        unit(x,y+n);
                        unit(x+n,y+2*n);
                        unit(x+2*n,y);
                    }
                }
            }
        }
        cout<<sum<<endl;
        return  0;
    }
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 50010
    
    struct node
    {
        int pre;
        int relation;
    };
    node p[N];
    
    int find(int x) //查找根结点
    {
        int temp;
        if(x == p[x].pre)
            return x;
        temp = p[x].pre; //路径压缩
        p[x].pre = find(temp);
        p[x].relation = (p[x].relation + p[temp].relation) % 3; //关系域更新
        return p[x].pre; //根结点
    }
    
    int main()
    {
        int n, k;
        int ope, a, b;
        int root1, root2;
        int sum = 0; //假话数量
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; ++i) //初始化
        {
            p[i].pre = i;
            p[i].relation = 0;
        }
        for(int i = 1; i <= k; ++i)
        {
            scanf("%d%d%d", &ope, &a, &b);
            if(a > n || b > n) //条件2
            {
                sum++;
                continue;
            }
            if(ope == 2 && a == b) //条件3
            {
                sum++;
                continue;
            }
            root1 = find(a);
            root2 = find(b);
            if(root1 != root2) // 合并
            {
                p[root2].pre = root1;
                p[root2].relation = (3 + (ope - 1) +p[a].relation - p[b].relation) % 3;
            }
            else
            {
                if(ope == 1 && p[a].relation != p[b].relation)
                {
                    sum++;
                    continue;
                }
                if(ope == 2 && ((3 - p[a].relation + p[b].relation) % 3 != ope - 1))
                {
                    sum++;
                    continue;}
            }
        }
        printf("%d
    ", sum);
        return 0;
    }
  • 相关阅读:
    软件架构学习小结
    Azure编程笔记(1):序列化复杂类型的TableEntity字段
    目标检測的图像特征提取之(一)HOG特征
    Gmail POP3设置
    MP3的频率、比特率、码率与音质的关系
    Oracle Dataguard 介绍
    【Github教程】史上最全github用法:github入门到精通
    Xcode6在10.9.4上面crash解决
    OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)
    调用ShellExecute所须要头文件
  • 原文地址:https://www.cnblogs.com/huangzzz/p/7979165.html
Copyright © 2020-2023  润新知