NC16884 食物链

题目

  • 原题地址:食物链
  • 题目编号:NC16884
  • 题目类型:扩展域并查集、带权并查集
  • 时间限制:C/C++ 3秒,其他语言6秒
  • 空间限制:C/C++ 65536K,其他语言131072K

1.题目大意

  • 懒得概括了,直接上题面:
  • 动物王国中有三类动物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),输出假话的总数。

2.题目分析

  • 学到了一个不错的函数:iota
  • iota(p, p + n + 1, 0):将p[0]p[1]、... 、p[n]依次赋值为01、... 、n
  • 看题解说有两种做法,开三倍空间的扩展域并查集就不学了,带权并查集性能更好一些
  • 取余三还不是很能理解,先保留个空

3.题目代码

#include <bits/stdc++.h>

using namespace std;

int a[50004], b[50004];
int find(int x) { return a[x]==x?x:(a[0]=find(a[x]),b[x]+=b[a[x]],a[x]=a[0]);}
int main() {
    int n, k, t, x, y, xx, yy, ans=0;
    cin >> n >> k;
    iota(a, a+n+1, 0);
    while(k--) {
        cin >> t >> x >> y, t--;
        if(x>n||y>n) ans++;
        else {
            xx = find(x), yy = find(y);
            if(xx==yy) {if((b[x]-b[y]-t)%3) ans++;}
            else a[xx] = yy, b[xx] = b[y] - b[x] + t;
        } 
    }
    cout << ans << endl;
}
posted @ 2022-09-03 18:46  仪战群儒  阅读(35)  评论(0)    收藏  举报