- 处理区间合并查询问题
- 合并集合
- 询问两个元素是否一个集合
AcWing 836模板:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int p[N];//祖宗节点
int n, m;
int find(int x){
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i ++) p[i] = i;
char ch[2];//避免换行问题
int a, b;
while(m --){
scanf("%s%d%d",&ch,&a,&b);
if(ch[0] == 'M') p[find(a)] = find(b);
else{
if(find(a) == find(b)) puts("Yes");
else puts("No");
}
}
return 0;
}
栗子 (ACWing 837):
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;
const int N = 1e5 + 10;
int p[N], s[N];//祖宗节点
int n, m;
int find(int x){
if(x != p[x]) p[x] = find(p[x]);
return p[x];
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i ++) p[i] = i, s[i] = 1;
string op;//避免换行空格的奇怪问题
int a, b;
while(m --){
cin >> op;
if(op == "C"){//合并a, b
scanf("%d%d",&a,&b);
if(find(a) != find(b)){
s[find(b)] += s[find(a)];//注意先加再合并
p[find(a)] = find(b);
}
}
else if(op == "Q1"){//询问a, b
scanf("%d%d",&a,&b);
if(find(a) == find(b)) puts("Yes");
else puts("No");
}
else{//a中所在连通块数量
scanf("%d",&a);
printf("%d\n",s[find(a)]);
}
}
return 0;
}
- 种类并查集
学习自
题意:
-
x y 是同一类动物
-
x 捕食 y
询问k次,有几句假话
具体见代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, k;//n种动物,k个询问
int p[N * 3];
int ans;
int find(int x){//查询
if(x != p[x]) p[x] = find(p[x]);
return p[x];
}
void merge(int x, int y){//合并
if(find(x) == find(y)) return ;
p[find(x)] = y;
}
int main(){
scanf("%d%d",&n,&k);
for(int i = 1; i <= 3 * n; i ++) p[i] = i;
int d, x, y;
while(k --){
scanf("%d%d%d",&d,&x,&y);
if((d == 2 && x == y) || x > n || y > n) {
ans ++;
continue;
}
if(d == 1) {
if(find(x) == find(y + n) || find(x) == find(y + 2 * n)){//同类不能捕食,出现反捕食
ans ++;
continue;
}
else {//3种动物
merge(x, y);//A类
merge(x + n, y + n);//B类
merge(x + 2 * n, y + 2 * n);//C类
}
}
else{
if(find(x) == find(y) || find(x) == find(y + n * 2)){//同类和反捕食
ans ++;
continue;
}
else{
merge(x, y + n);//A->B
merge(x + n, y + 2 * n);//B->C;
merge(x + 2 * n, y);//C->A
}
}
}
printf("%d\n",ans);
return 0;
}