题目
分析
对于动物 a 和 b,我们可能有 a 吃 b,a 与 b 同类,a 被 b 吃。即存在三种关系:a 是 b 的同类、猎物、天敌,那我们要给数组分配三倍的空间来维护这层关系。依题意:
① 第一种说法是“1 x y”,表示 x 和 y 是同类。
假如不是同类,那么 x 与 y 是天敌或者猎物关系,即 getf(a + n) == getf(b) || getf(a + 2 * n) == getf(b)
② 第二种说法是“2 x y”,表示 x 吃 y 。
假如不是天敌, 那么 x 与 y 是同类或者猎物关系, 即 getf(a) == getf(b) || getf(a + n) == getf(b)
AC代码
#include <iostream>
#include <cstdio>
using namespace std;
int ans = 0;
int f[50005 * 3];
int n, k;
// 并查集模板
int getf(int x)
{
if (f[x] == x)
{
return x;
}
return f[x] = getf(f[x]);
}
void merge(int x, int y)
{
int t1 = getf(x);
int t2 = getf(y);
if (t1 != t2)
{
f[t1] = t2;
}
}
void init()
{
for (int i = 1; i <= n * 3; i++)
{
f[i] = i;//同类 猎物 天敌
}
}
int main() {
scanf("%d%d", &n, &k);
init();
for (int i = 0; i < k; i++)
{
int c, a, b;
scanf("%d %d %d", &c, &a, &b);
if (a > n || b > n)
{
ans++;
continue;
}
if (c == 1)
{
if (getf(a + n) == getf(b) || getf(a + 2 * n) == getf(b)) // 不是同类,即a是b的天敌或a是b的猎物
{
ans++;
continue;
}
// 是同类,分别合并三类动物
merge(a, b); merge(a + n, b + n); merge(a + 2 * n, b + 2 * n);
}
else
{
if (a == b)
{
ans++;
continue;
}
if (getf(a) == getf(b) || getf(a + n) == getf(b)) //不是天敌关系,即a是b的同类或者猎物
{
ans++;
continue;
}
// 是天敌关系
merge(a + 2 * n, b);
merge(a + n, b + 2 * n);
merge(a, b + n);
}
}
cout << ans << endl;
return 0;
}