zoukankan      html  css  js  c++  java
  • 种类并查集

    传送门

    食物链

    题意:

    有三种动物,其食物链形成一个环,即A吃B,B吃C,C吃D。

    现在有n个动物,每个动物都属于ABC中的一种,给你k个描述,判断这k种描述的真假,求出假话的总数。

    每次描述输入三个数字d,x, y。

    d = 1时,表示X和Y是同类

    d = 2时,表示X吃Y

    思路:

    对于每个动物,都有三种可能,可能是A,可能是B,可能是C

    所以我们开三倍的数组,将一个数组分成三份来判断——1 到 n是假设一,n + 1 到n * 2是假设二,n * 2 + 1 到 n * 3是假设三

    1A 2A 3A

    1B 2B 3B

    1C 2C 3C

    假设1是A

    当d=1时,说明2和1是同类,则2就是A。

    我们只需要判断1A和2A是不是同类即可

    当d=2时,说明1吃2,根据题意,A吃B,所以2是B。

    我们只需要判断1A和2B是不是同类即可

    假设1是B

    当d=1时,说明2和1是同类,则2就是B

    我们就判断1B和2B是不是同类即可

    当d=2时,说明1吃2,根据题意,B吃C,所以2是C

    我们只需要判断1B和2C是不是同类即可

    假设1是C

    当d=1时,说明2和1是同类,则2就是C

    我们只需要判断1C和2C是不是同类即可

    当d=2时,说明1吃2,根据题意,C吃A,所以2是A

    我们只需要判断1C和2A是不是同类即可

    所以对于d = 1,说明1和2必须是同类,也就是find(1) = find(2),抽象化一下就是find(x) == find(y) find(x + n) == find(y + n) find(x + n * 2) == find(y + n * 2),我们只需要找到不等的情况,让sum++即可,对于相等的情况来说,就是正确的,我们就把三种情况分别进行合并

    对于d = 2,说明1吃2,根据题中的对应关系,抽象化成find(x) = find(y + n),find(x + n) = find(y + n * 2), find(x + n * 2) = find(y),操作同上

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 150000 + 5
    typedef  long long ll ;
    
    inline int IntRead(){
        char ch = getchar();int s = 0, w = 1;
        while(ch < '0' || ch > '9'){
            if(ch == '-') w = -1;
            ch = getchar();}
        while(ch >= '0' && ch <= '9'){
            s = s * 10 + ch - '0';ch = getchar();}
        return s * w;
    }
    
    int n, fa[MAX];
    //初始化一定要记得是对n * 3 的数进行初始化
    void init(){
        for(int i = 1; i <= n * 3; ++i) fa[i] = i;
    }
    
    int find(int x){//找根
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    }
    
    void emerge(int x, int y)
    {
        fa[find(x)] = find(y);
    }
    
    int main()
    {
        int d, k ,x, y, sum = 0;
        cin>>n>>k;
        init();
        for(int i = 1; i <= k; ++i){
            cin>>d>>x>>y;
            if(x > n || y > n){
                sum++;
                continue;
            }
            //x 代表x是a,x + n代表x是b, x + 2 * n代表x是c
            if(d == 1){
                if(find(x) == find(y + n) || find(x) == find(y + n * 2)){
                    sum++;
                    continue;
                }
                emerge(x, y);//合并
                emerge(x + n, y + n);
                emerge(x + n * 2, y + n * 2);
            }
            else if(d == 2){
                if(find(x) == find(y) || find(x) == find(y + n * 2)){
                    sum++;
                    continue;
                }
                emerge(x, y + n);
                emerge(x + n, y + n * 2);
                emerge(x + n * 2, y);
            }
        }
        cout<<sum<<endl;
        return 0;
    }
    
    不是所有的牛奶都叫特仑苏,也不是所有的人都叫猪猪
  • 相关阅读:
    Linkedin工程师是如何优化他们的Java代码的
    如何调试 Android 上 HTTP(S) 流量
    Facebook工程师是如何改进他们Android客户端的
    modified: xxx(modified content, untracked content)
    在Android工程中加入AIDL文件时,gen目录生成的文件报错-问题解决
    Ubuntu14.04LTS下使用eclipse搭建Cocos2d-x的Android环境
    Ubuntu Linux下安装Oracle JDK
    查看Android源码版本
    Ubuntu Linux下安装Oracle JDK
    Android Initializing a Build Environment
  • 原文地址:https://www.cnblogs.com/chelsea0901/p/14438116.html
Copyright © 2011-2022 走看看