要求
有N只动物,分别编号为1,2,…,N。所有动物都属于A,B,C中的其中一种。已知A吃B、B吃C、C吃A。按顺序给出下面的二种信息共K条
* 第一种:x和y属于同一种类
* 第二种:x吃y
然而这些信息有可能会出错。有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的x和y不在1,2,…,N的范围内。求在K条信息中有多少条是不正确的。计算过程中,我们将忽视诸如此类的错误信息。
限制条件
- 1 <= N <= 50000
- 0 <= K <= 100000
输入格式
第一行输入N,K
接下来K行输入
第几种信息(1,2) 编号a 编号b
输出格式
输出有多少条是不正确的
测试输入
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
测试输出
3
解题思路
用并查集进行实现,分别扩展par数组为N * 3 ,用来记录A、B、C
代码
#include <iostream>
#include <cmath>
using namespace std;
int par[150001];
int rank[150001];
void init(int n) {
for (int i = 0; i < n; i++) {
par[i] = i;
rank[i] = 0;
}
}
int find(int x) {
if (par[x] == x) {
return x;
} else {
return par[x] = find(par[x]);
}
}
void unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return;
} else if (rank[x] < rank[y]){
par[x] = y;
} else {
par[y] = x;
if (rank[x] == rank[y]) {
rank[x]++;
}
}
}
bool same(int x, int y) {
return find(x) == find(y);
}
int N, K;
int T[1001], X[1001], Y[1001];
int main() {
cin >> N;
cin >> K;
for (int i = 0; i < K; i++) {
cin >> T[i] >> X[i] >> Y[i];
}
init(N * 3);
int ans = 0;
for (int i = 0; i < K; i++) {
int t = T[i];
int x = X[i] - 1;
int y = Y[i] - 1;
if (x < 0 || N <= x || y < 0 || N <= y) {
ans++;
continue;
}
if (t == 1) {
if (same(x, y + N) || same(x, y + 2 * N)) {
ans++;
} else {
unite(x, y);
unite(x + N, y + N);
unite(x + N * 2, y + N * 2);
}
} else {
if (same(x, y) || same(x, y + 2 * N)) {
ans++;
} else {
unite(x, y + N);
unite(x + N, y + 2 * N);
unite(x + 2 * N, y);
}
}
}
cout << ans << endl;
return 0;
}