解法一:算距离,使用带边权并查集;
code:
#include<bits/stdc++.h>
using namespace std;
const int N=50010;
int d[N],p[N];
int find(int x){
if(p[x]!=x){
int t=find(p[x]);
d[x]+=d[p[x]];//距离
p[x]=t;
}
return p[x];
}
int main(){
int n,m,res=0;
cin>>n>>m;
for(int i=1;i<=n;i++) p[i]=i;
while(m--){
int t,x,y;
cin>>t>>x>>y;
if(x>n||y>n) res++;
else{
int px=find(x),py=find(y);
if(t==1){
if(px==py&&(d[x]-d[y])%3) res++;//判定冲突
else if(px!=py){
p[px]=py;
d[px]=d[y]-d[x];
}
}else{
if(px==py&&(d[x]-d[y]-1)%3) res++;//判定冲突
else if(px!=py){
p[px]=py;
d[px]=d[y]-d[x]+1;//留存值
}
}
}
}
cout<<res<<endl;
return 0;
}
解法二:使用拓展域并查集,x+n表示x+n吃x,x+2*n表示x+2*n被x吃:
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 15e4 + 10;
int p[N], ans, n, k;
inline int find(int x) {
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
inline bool check(int x, int y) { return find(x) == find(y); }
inline void hb(int x, int y) {
x = find(x), y = find(y);
if (x != y) {
p[x] = y;
}
}
int main() {
cin >> n >> k;
for (int i = 1; i <= n * 3; i++) p[i] = i;
while (k--) {
int z, x, y;
cin >> z >> x >> y;
if (x > n || y > n)
ans++;
else if (z == 1) {
if (check(x, y + n) || check(x, y + 2 * n)) {
ans++;
} else {
hb(x, y);
hb(x + n, y + n);
hb(x + 2 * n, y + 2 * n);
}
} else if (z == 2) {
if (check(x, y) || check(x, y + 2 * n)) {
ans++;
} else {
hb(x, y + n);
hb(x + n, y + 2 * n);
hb(x + 2 * n, y);
}
}
}
cout << ans << endl;
return 0;
}