种类并查集

食物链

https://ac.nowcoder.com/acm/problem/16884

传送门

食物链

题意:

有三种动物,其食物链形成一个环,即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;
}
全部评论

相关推荐

像好涩一样好学:这公司我也拿过 基本明确周六加班 工资还凑活 另外下次镜头往上点儿
点赞 评论 收藏
分享
10-06 12:46
门头沟学院 Java
跨考小白:定时任务启动
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务