W4 - 食物链(POJ-1182)

题目描述

在这里插入图片描述

Input & Output

在这里插入图片描述

Sample

在这里插入图片描述

Code

/*
 * @Description: 食物链
 * @version: 
 * @Author: 
 * @Date: 2021-04-21 22:14:45
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-04-21 23:26:27
 */
// self
// 看了提示,提交五次,一次TLE,三次WA
// TLE的可能原因(不能确定):cin大数导致TLE 或者 开始设计的Find函数用递归找根节点,且每次循环开始前刷新所有结点的根节点导致TLE 或者 两者兼有
// WA原因:在处理type==2的情况时写成了Find(a)==Find(b)||Find(b)==Find(a)了,少了一个+num_animal
// a吃b是假话的情况是:ab是同类或b吃a
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int Find(int x, vector<int> &father)
{
    int t = x;
    while (father[t] != t)
        t = father[t];
    // 找一次根节点,把该结点到根节点路上所有结点的父节点更改为根节点
    // 不明白的话可以画一个图模拟一下各变量指向和变化的情况
    while (x != t)
    {
        int temp = father[x];
        father[x] = t;
        x = temp;
    }
    return t;
}
void Merge(int a, int b, vector<int> &father)
{
    int fa = Find(a, father);
    int fb = Find(b, father);
    if (fa != fb)
        father[fa] = fb;
}
int main()
{
    unsigned sum = 0U;
    int num_animal, num_bond;
    // cin >> num_animal >> num_bond;
    scanf("%d %d", &num_animal, &num_bond);
    vector<int> father(3 * (num_animal + 1), -1);
    for (int i = 1; i <= 3 * num_animal; i++)
        father[i] = i;
    while (num_bond--)
    {
        int type, a, b;
        // cin >> type >> a >> b;
        scanf("%d %d %d", &type, &a, &b);
        // 大于编号的情况
        if (a > num_animal || b > num_animal || a < 1 || b < 1)
        {
            sum++;
            continue;
        }
        // 同类相食的情况
        if (type == 2 && a == b)
        {
            sum++;
            continue;
        }
        if (type == 1)
        {
            // 若a吃b,或b吃a则是假话
            if (Find(a, father) == Find(b + num_animal, father) || Find(b, father) == Find(a + num_animal, father))
            {
                sum++;
                continue;
            }
            // 是真话,a b合并,a+n b+n合并,a+2*n b+2*n合并
            Merge(a, b, father);
            Merge(a + num_animal, b + num_animal, father);
            Merge(a + 2 * num_animal, b + 2 * num_animal, father);
        }
        else if (type == 2)
        {
            // 若ab同类 或b吃a的话是假话
            if (Find(a, father) == Find(b, father) || Find(b, father) == Find(a + num_animal, father))
            {
                sum++;
                continue;
            }
            Merge(a, b + num_animal, father);
            Merge(a + num_animal, b + 2 * num_animal, father);
            Merge(a + 2 * num_animal, b, father);
        }
    }
    cout << sum << endl;
    // system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jian圣楠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值