我用三个标记数组来标记对应的动物属于A B或C
但是这样写一直WA, 试的样例也都过了,不清楚问题出在哪里
自己的代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 100010
using namespace std;
/*
*p[i] == 0 i为A生物
*p[i] == 1 i为B生物
*p[i] == 2 i为C生物
*/
int p[MAXN];
int main(void) {
int n, k, ans, d, x, y;
scanf("%d%d", &n, &k);
ans = 0;
memset(p, -1, sizeof(p));
while(k--) {
scanf("%d%d%d", &d, &x, &y);
if(x>n || y>n) {
ans++;
continue;
}
if(d==2 && x==y) {
ans++;
continue;
}
if(p[x]==-1 && p[y]==-1) {//x和y之前都没有出现过
if(d == 1) {
p[x] = p[y] = 0;
}
else if(d == 2) {
p[x] = 0;
p[y] = 1;
}
} else if(p[x]==-1 && p[y]!=-1) {//x没有出现过,y出现过
if(d == 1)
p[x] = p[y];
else if(d == 2) {
p[x] = (p[y]+2)%3;
}
} else if(p[x]!=-1 && p[y]==-1) {//x出现过,y没有出现过
if(d == 1)
p[y] = p[x];
else if(d == 2) {
p[y] = (p[x]+1)%3;
}
} else if(p[x]!=-1 && p[y]!=-1) {//x和y都出现过
if(d==1 && p[x]!=p[y])
ans++;
else if(d==2 && (p[x]+1)%3!=p[y])
ans++;
}
}
cout << ans << endl;
return 0;
}
看了下网上用并查集+路径压缩方法做的
方法很巧妙,甚至让我有种答案是碰巧做出来的感觉
详细的解释请戳这里:点击打开链接
思路是在路径压缩的过程中同时更新当前节点的父节点和它与父节点之间的关系
代码如下:
#include <stdio.h>
#include <string.h>
#define MAXN 50001
int p[MAXN], r[MAXN];
int ans, n;
void init() {
int i;
for(i=1; i<=n; ++i)
p[i] = i;
ans = 0;
memset(r, 0, sizeof(r));
}
int find(int x) {
if(x != p[x]) {
int f = find(p[x]);//找到x的根节点
r[x] = (r[x]+r[p[x]])%3;//确立x和根节点之间关系
p[x] = f;
}
return p[x];
}
bool Union(int x, int y, int d) {
int fx, fy;
fx = find(x);
fy = find(y);
if(fx == fy) {
if((r[y]-r[x]+3)%3 != d-1)
return true;
return false;
}
p[fy] = fx;
r[fy] = (r[x]-r[y]+d+2)%3;
return false;
}
int main(void) {
int k, x, y, d;
scanf("%d%d", &n, &k);
init();
while(k--) {
scanf("%d%d%d", &d, &x, &y);
if(x>n || y>n || (x==y && d==2))
ans++;
else if(Union(x, y, d))
ans++;
}
printf("%d\n", ans);
return 0;
}