题目大意:有三类动物,A, B, C。A吃B,B吃C,C吃A。现在有n个动物(属于以上三类),
m个陈述:d u v, d==1表示u和v为同类,d==2表示u吃v。
三种情况当前的话为假话
(1)当前的话与前面的话冲突
(2)当前的话中u或者v大于n
(3)当前的话表示u吃u
问假话的数量
fa[i]表示i的父亲的编号
relation[i]表示i与其父亲的关系:0表示相同,1表示被父亲吃,2表示吃父亲
!!!关系的传递:类比向量:若(a, b)表示a对b的关系,则
(1)(a, b) = (a, c) + (c, b);
(2)(a, b) = 3 - (b, a);或者(a, b)+(b, a)=3;
#include <cstdio>
using namespace std;
const int maxn = 50010;
int fa[maxn], relation[maxn];
void init(int n)
{
for(int i = 1; i <= n; ++i)
{
fa[i] = i;
relation[i] = 0;
}
}
int findf(int x)
{
int tmp;
if(x == fa[x]) return x;
tmp = fa[x];
fa[x] = findf(fa[x]);
relation[x] = (relation[x] + relation[tmp]) % 3;//更新x和根节点的关系
return fa[x];
}
int main()
{
int i, n, m, d, u, v, ans = 0;
int f1, f2;
scanf("%d %d", &n, &m);
init(n);
for(i = 1; i <= m; ++i)
{
scanf("%d %d %d", &d, &u, &v);
if(u > n || v > n)
{
++ans;
continue;
}
if(d == 2 && u == v)
{
++ans;
continue;
}
f1 = findf(u);
f2 = findf(v);
if(f1 != f2)
{//合并两个集合
fa[f2] = f1;
relation[f2] = (3-relation[v] + (d-1) + relation[u]) % 3;//更新v的父节点和u的父节点的关系(向量法)
continue;
}
if(d == 1 && relation[u] != relation[v])
{
++ans;
continue;
}
if(d == 2 && (3-relation[u] + relation[v]) % 3 != d-1)
{
++ans;
continue;
}
}
printf("%d\n", ans);
return 0;
}