一、扩展域写法
具体代码如下
#include<iostream>
#include<cstring>
#include<unordered_map>
using namespace std;
const int N = 40010, Base = N / 2;
int n, m;
int p[N];
unordered_map<int, int> S;
int get(int x){
if(!S.count(x)) S[x] = ++ n;
return S[x];
}
int find(int x){
if(x != p[x]) p[x] = find(p[x]);
return p[x];
}
int main(){
scanf("%d%d", &n, &m);
n = 0;
for(int i = 0; i < N; ++ i) p[i] = i;
int res = m;
for(int i = 0; i < m; ++ i){
int a, b;
string op;
cin >> a >> b >> op;
a = get(a - 1), b = get(b);
if(op == "even"){
if(find(a + Base) == find(b)){
res = i;
break;
}
p[find(a)] = find(b);
p[find(a + Base)] = find(b + Base);
}else{
if(find(a) == find(b)){
res = i;
break;
}
p[find(a + Base)] = find(b);
p[find(a)] = find(b + Base);
}
}
printf("%d\n", res);
return 0;
}
二、带边权的并查集写法
具体代码如下
#include<iostream>
#include<cstring>
#include<unordered_map>
using namespace std;
const int N = 40010, Base = N / 2;
int n, m;
int p[N], d[N];
unordered_map<int, int> S;
int get(int x){
if(!S.count(x)) S[x] = ++ n;
return S[x];
}
int find(int x){
if(x != p[x]){
int t = find(p[x]);
d[x] += d[p[x]] % 2;
p[x] = t;
}
return p[x];
}
int main(){
scanf("%d%d", &n, &m);
n = 0;
for(int i = 0; i < N; ++ i) p[i] = i;
int res = m;
for(int i = 0; i < m; ++ i){
int a, b;
string op;
cin >> a >> b >> op;
a = get(a - 1), b = get(b);
int pa = find(a), pb = find(b), t = 0;
if(op == "odd") t = 1;
if(pa == pb){
if(abs((d[a] - d[b])) % 2 != t){
res = i;
break;
}
}else{
p[pa] = pb;
d[pa] = t - d[a] - d[b];
}
}
printf("%d\n", res);
return 0;
}