您的位置:首页 > 其它

UVA11987:Almost Union-Find (并查集的删除)

2017-09-04 21:02 253 查看
题意:

三个指令分别为:1:合并p,q所在的两个集合;

  2:将p移动到q的集合中。

  3:查询p所在集合的元素个数和元素之和。

难点在于第二个指令,不能简单的合并,因为p有可能是根节点。

所以再开一个id数组,记录p的编号。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define mx 100010
using namespace std;
int fa[mx],sum[mx],id[2*mx];
int cen[mx],n,m,de;
void init(){
for(int i = 1;i < mx;i ++){
id[i] = sum[i] = fa[i] = i;
cen[i] = 1;
}
de = n;
}
int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void uni(int x,int y){
x = find(x);
y = find(y);
if(x != y){
fa[x] = y;
sum[y] += sum[x];
cen[y] += cen[x];
}
}
void move(int x){
int fx = find(id[x]);
sum[fx] -= x;
cen[fx] -= 1;
id[x] = ++de;
cen[id[x]] = 1;
fa[id[x]] = id[x];
sum[id[x]] = x;
}

int main(){

while(scanf("%d%d",&n,&m)!=EOF){
int cm,a,b;
init();
for(int i = 0; i < m; i++){
scanf("%d",&cm);
if(cm == 1){
scanf("%d%d",&a,&b);
uni(id[a],id[b]);
}
else if(cm == 2){
scanf("%d%d",&a,&b);
if(find(id[a]) == find(id[b])) continue;
move(a);
uni(id[a],id[b]);
}
else {
scanf("%d",&a);
a=find(id[a]);
cout<<cen[a]<<" "<<sum[a]<<endl;
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息