836. 合并集合
https://www.acwing.com/problem/content/838/
# include<iostream>
using namespace std;
const int N = 100010;
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;
while(m--){
char op[2];
int a,b;
scanf("%s%d%d",op,&a,&b);
if(op[0]=='M') p[find(a)] = find(b);
else{
if(find(a)==find(b)) puts("Yes");
else puts("No");
}
}
}
837. 连通块中点的数量
https://www.acwing.com/problem/content/839/ 此题中的n个点在添加了边后,会形成多个连通图,每个连通图可以看做一个集合。查询两个点是否在一个连通块中等价于查询两个数是否在同一集合。所以可以使用并查集来解决,并查集的功能:1、将两个集合以近似O(1)的复杂度进行合并 2、询问两个元素是否在一个集合中。
具体如下:
- 把根节点作为集合的标号,在a、b之间添加一条边就等价于将两个集合合并,等价于将a所在树的根的节点即
find(a) 设为 b所在树的根即find(b) ,使a所在树 变成 b所在树的子树。同时为了求取第三个问题,要设置一个数组capacity记录每个连通图的点数 即 每个集合的元素数(通过各个树的根确定集合),在合并时如果两个点属于不同的集合则合并后的capacity[rootB]为capacity[rootB]+capacity[rootA] 。 - 查询两个点是否在同一连通块中,等价于查询两个数的集合编号是否相等(是否属于同一个根)
- 询问a所在连通块的数量,等价于求
capacity[find(a)] ,
# include <iostream>
using namespace std;
const int N = 100010;
int p[N],capacity[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;
capacity[i] = 1;
}
while(m--){
int a, b;
char op[5];
scanf("%s", op);
if(op[0] == 'C') {
scanf("%d%d", &a, &b);
if(find(a) != find(b))
capacity[find(b)] += capacity[find(a)];
p[find(a)] = find(b);
}else if(op[1] == '1') {
scanf("%d%d",&a,&b);
if(find(a) == find(b)) puts("Yes");
else puts("No");
}else {
scanf("%d",&a);
printf("%d\n",capacity[find(a)]);
}
}
return 0;
}
240. 食物链
https://www.acwing.com/problem/content/242/
# include <iostream>
using namespace std;
const int N = 50010;
int p[N],d[N];
int n,k,res;
int find(int x){
if(p[x] != x) {
int tmp = find(p[x]);
d[x] += d[p[x]];
p[x] = tmp;
}
return p[x];
}
int main(){
cin>>n>>k;
for(int i = 1; i <= n; i++){
p[i] = i;
}
while(k--){
int t,x,y;
cin>>t>>x>>y;
if(x > n || y > n) res++;
else if(t==1){
int rootX = find(x), rootY = find(y);
if(rootX == rootY && (d[x] - d[y]) % 3 != 0) res ++;
else if(rootX != rootY) {
p[rootX] = rootY;
d[rootX] = d[y] - d[x];
}
}else {
int rootX = find(x), rootY = find(y);
if(rootX == rootY && (d[x] - d[y] - 1) % 3 != 0) res ++;
else if(rootX != rootY) {
p[rootX] = rootY;
d[rootX] = d[y] + 1 - d[x] ;
}
}
}
cout<<res<<endl;
}
|