并查集怎么搞?POJ1182 食物链

并查集

并查集是一种用来管理元素分组情况的数据结构。
可以进行如下操作:
· 查询元素a和元素b是否属于同一组;
· 合并元素a和元素b所在的组。

操作

初始化

int par[N], dth[N];

void init(int n) {
    for (int i = 0; i <= n; i++) {
        par[i] = i;
        dth[i] = 0;
    }
}

查询元素的"祖先"

祖先:元素所在的组中最顶层的结点,即par[x] = x的结点。

int find(int x) {
    return x == par[x] ? x : find(par[x]);
}


int find(int x) {
	while(x!=par[x]) x = par[x];
	return x;
}

查询元素是否同组

bool same(int x, int y) {
    return find(x) == find(y);
}

合并

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    else par[x] = y;
}

POJ1182 食物链

在这里插入图片描述

题解

这里有三种生物A、B、C。
食物链为:A->B->C->A。
对于输入的数据,我们并不能确定是这三种中的哪一种,当然,我们也不需要确定,只需要推导出矛盾的点就可以。

对于任意生物X, X_n表示其为A,X_2n表示其为B, X_3n表示其为C。
那么如果我们得到a吃b的信息,就可以得出:
a属于n && b属于2na属于2n && b属于3n, 以及a属于3n && b 属于n的信息。
如果接下来出现与这些情况不符的信息,就可以推定其真值为假。

同理,如果我们得到a,b同类的消息,就可以得出:
a属于n && b属于na属于2n && b属于2n, 以及a属于3n && b 属于3n的信息。
如果接下来出现与这些情况不符的信息,就可以推定其真值为假。

AC代码

#include <iostream>

using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(a, b) memcpy(a, b, sizeof(b))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;
const int N = 5e4 + 10;
int n, k;
int par[N * 3];

void init(int t) {
    for (int i = 1; i <= t; i++) {
        par[i] = i;
    }
}

int find(int x) {
    return x == par[x] ? x : find(par[x]);
}

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    else par[x] = y;
}

bool same(int x, int y) {
    return find(x) == find(y);
}

int main() {
    scanf("%d%d", &n, &k);
    int cnt = 0;
    init(n * 3);
    while (k--) {
        int d, x, y;
        scanf("%d%d%d", &d, &x, &y);//1-N
        if (x <= 0 || y <= 0 || x > n || y > n || (d == 2 && x == y)) {
            cnt++;
            continue;
        }
        if (d == 1) {
            if (same(x, y + n) || same(x, y + 2 * n)) cnt++;
            else {
                unite(x, y);
                unite(x + n, y + n);
                unite(x + 2 * n, y + 2 * n);
            }
        } else if (d == 2) {
            if (same(x, y) || same(x, y + 2 * n)) cnt++;
            else {
                unite(x, y + n);
                unite(x + n, y + 2 * n);
                unite(x + 2 * n, y);
            }
        }
    }
    printf("%d\n", cnt);
    return 0;
}

Tips

笔者开始用的关闭同步流的cin和cout,wa了三发hhhh。
scanf比它快。
此外输出\n比endl快。


觉得不错的话记得点个赞呀~~你的赞就是笔者最大的动力

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值