题意:有 N 只动物, 编号为1 - N,这 N 只动物为别为 A、B、C 三类中的一类,已知:A 吃 B、B 吃 C、C 吃 A,同类不互吃。给你 K 条条件(a b c): a == 1 b 和 c 为同类; a == 2 为b 吃 c。条件从上到下依次满足(当编号大于N,也为错),问你有几条错误条件。
思路:并查集。。。一般并查集我们只需维护一种关系,这道题有两种关系同类和捕食关系。如何维护:因为我们并不知道该动物究竟属于哪类,那么我设 1 ~ N 为 A 类, N+1 ~ N+N 为 B 类,1+2N ~ 3N 为 C 类。其实 1、1+N、1+2N 是同个动物,这样我们就不用纠结于他是A类会怎样、B类会怎样、C类会怎样了。
1、若条件为 1 b c 时,说明 b 和 c 为同类,那么我先查看之前是否有条件说 b 和 c 为捕食关系,若有错误条件数++,否则合并(b, c)、(b+N, c+N)、(b+2N,c+2N);
2、若条件为 2 b c 时,说明 b 和 c 为捕食关系,则查看之前是否有条件说b 和 c 为同类,若没有则将合并(b, c+N)、(b+N, c+2N)、(b+2N,c)。
注:只能单组数据。。。while(~scanf。。。)什么的会 WA 的
代码实现:
#include <iostream>
#include <cstdio>
using namespace std;
int num[160000];
int find_fa(int x)
{
while(num[x] != x)
{
x = num[x];
}
return x;
}
bool Same(int a, int b)
{
int aa = find_fa(a);
int bb = find_fa(b);
if(aa == bb)
return true;
return false;
}
void Join(int a, int b)
{
int aa = find_fa(a);
int bb = find_fa(b);
if(aa != bb)
{
num[aa] = bb;
}
return ;
}
int main()
{
int N, K;
scanf("%d%d", &N, &K);
int a, b, c;
int ans = 0;
memset(num, -1, sizeof(num));
for(int i = 0; i < K; i++)
{
scanf("%d%d%d", &a, &b, &c);
if(b > N || c > N)
{
ans++;
continue;
}
if(num[b] == -1)
{
num[b] = b;
num[b+N] = b + N;
num[b+2*N] = b + 2*N;
}
if(num[c] == -1)
{
num[c] = c;
num[c+N] = c + N;
num[c+2*N] = c + 2*N;
}
if(a == 1)
{
if(Same(b, c+N) || Same(c, b+N))
ans++;
else
{
Join(b, c);
Join(b+N, c+N);
Join(b+2*N, c+2*N);
}
}
else
{
if(Same(b, c) || Same(c, b+N))
ans++;
else
{
Join(b, c+N);
Join(b+N, c+2*N);
Join(b+2*N, c);
}
}
}
printf("%d\n", ans);
return 0;
}
若有错,请大家多多指教^ ^