带权并查集
#include<iostream>
using namespace std;
const int N = 100010;
int p[N],d[N];
int n,k;
int res = 0;
int find(int x){
if(p[x] != x){
int rot = find(p[x]);
d[x] += d[p[x]];
p[x] = rot;
}
return p[x];
}
int main(){
cin >> n >> k;
for(int i = 1;i <= n;i ++) p[i] = i;
while(k --){
int op,a,b;
cin >> op >> a >> b;
if(a > n || b > n) res ++;
else{
int pa = find(a),pb = find(b);
if(op == 1){
if(pa == pb && (d[a] - d[b]) % 3) res ++;
else if(pa != pb){
p[pa] = pb;
d[pa] = d[b] - d[a];
}
}else{
if(pa == pb && (d[a] - d[b] - 1) % 3) res ++;
else if(pa != pb){
p[pa] = pb;
d[pa] = d[b] - d[a] + 1;
}
}
}
}
cout << res;
}
拓展域
#include<iostream>
using namespace std;
const int N = 50010;
int p[N * 3];
int n,k;
int res = 0;
int find(int x){
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
void meg(int a,int b){
p[find(a)] = find(b);
}
int main(){
cin >> n >> k;
for(int i = 1;i <= n * 3;i ++) p[i] = i;
while(k --){
int op,a,b;
cin >> op >> a >> b;
if(a > n || b > n) res ++;
else{
int pa1 = find(a),pa2 = find(a + n),pa3 = find(a + 2 * n);
int pb1 = find(b),pb2 = find(b + n),pb3 = find(b + 2 * n);
if(op == 1){
if(pa1 == pb2 || pa1 == pb3) res ++;
else{
meg(pa1,pb1);
meg(pa2,pb2);
meg(pa3,pb3);
}
}else{
if(pa1 == pb1 || pa1 == pb3) res ++;
else{
meg(pa1,pb2);
meg(pa2,pb3);
meg(pa3,pb1);
}
}
}
}
cout << res;
}
带权并查集
有序离散化(排序、去重、二分)
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int n,m;
int p[N],d[N];
int alls[N];
struct query{
int l,r;
int sex;
} q[N];
int find(int x){
if(p[x] != x){
int rot = find(p[x]);
d[x] ^= d[p[x]];
p[x] = rot;
}
return p[x];
}
void init(){
cin >> n >> m;
int t = 0;
for(int i = 0;i < m;i ++){
string s;
cin >> q[i].l >> q[i].r >> s;
if(s == "odd") q[i].sex = 1;
else q[i].sex = 0;
alls[++ t] = q[i].l;
alls[++ t] = q[i].r;
}
sort(alls + 1,alls + 1 + t);
n = unique(alls + 1,alls + 1 + t) - alls - 1;
for(int i = 1;i <= n;i ++) p[i] = i;
}
int main(){
init();
int res = m;
for(int i = 0;i < m;i ++){
int l = lower_bound(alls + 1,alls + 1 + n,q[i].l - 1) - alls;
int r = lower_bound(alls + 1,alls + 1 + n,q[i].r) - alls;
int pl = find(l),pr = find(r);
if(pl == pr){
if((d[l] ^ d[r]) != q[i].sex){
res = i;
break;
}
}else{
p[pl] = pr;
d[pl] = d[l] ^ d[r] ^ q[i].sex;
}
}
cout << res;
}
无序离散化
#include<iostream>
#include<unordered_map>
using namespace std;
const int N = 100010;
int p[N],d[N];
int n,m;
unordered_map<int,int> s;
int find(int x){
if(p[x] != x){
int rot = find(p[x]);
d[x] ^= d[p[x]];
p[x] = rot;
}
return p[x];
}
int get(int x){
if(!s[x]) s[x] = ++n;
return s[x];
}
int main(){
cin >> n >> m;
n = 0;
int res = m;
for(int i = 1;i <= m;i ++){
int a,b;
string c;
cin >> a >> b >> c;
a = get(a - 1),b = get(b);
//动态初始化 cite(https://www.acwing.com/solution/content/58761/)
if(!p[a]) p[a] = a;
if(!p[b]) p[b] = b;
int pa = find(a),pb = find(b);
int t = (c == "even" ? 0 : 1);
if(pa == pb){
if((d[a] ^ d[b]) != t){
res = i - 1;
break;
}
}else{
p[pa] = pb;
d[pa] = d[a] ^ d[b] ^ t;
}
}
cout << res;
}
无序离散化 + 扩展域
#include<iostream>
#include<unordered_map>
using namespace std;
const int N = 10010;
int p[N * 2];
int n,m;
unordered_map<int,int> alls;
int len = 0;
int find(int x){
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int get(int x){
if(!alls[x]) alls[x] = ++ len;
return alls[x];
}
void meg(int x,int y){
p[find(x)] = find(y);
}
int main(){
cin >> n >> m;
for(int i = 1;i <= N * 2;i ++) p[i] = i;
int res = m;
for(int i = 0;i < m;i ++){
int a,b;
string c;
cin >> a >> b >> c;
a = get(a - 1),b = get(b);
int pa1 = find(a),pa2 = find(a + N);
int pb1 = find(b),pb2 = find(b + N);
if(c == "even"){
if(pa1 == pb2){
res = i;
break;
}else{
meg(pa1,pb1);
meg(pa2,pb2);
}
}else{
if(pa1 == pb1){
res = i;
break;
}else{
meg(pa1,pb2);
meg(pa2,pb1);
}
}
}
cout << res;
}