带权并查集|连通、集合最值、集合元素个数、到根的距离

带权并查集

两道题合起来,说清楚并查集的作用有哪些

连通、集合最值、集合元素个数、到根的距离...

#include<bits/stdc++.h>
using namespace std;

/*查找、合并|统计集合个数、集合最大值、每个集合的元素个数、到根的距离*/

const int maxn = 1e6+10;

int n,m;
int father[maxn]; 
int size[maxn];//集合中元素的个数 
int maxs[maxn];//集合中最大值 
int dist[maxn];//到根节点的距离 
int setNums = 0;

void init(){
    for(int i=1;i<=n;i++){
        father[i] = i;
        size[i] = 1;
        maxs[i] = i;
        dist[i] = 0;
    }
}

//find循环写法 
int Find(int x){
    int p,tmp;
    p = x;
    while(father[x] != x){
        x = father[x];//找到祖先节点 
    }
    while(p!=x){//更新p(原x)的父辈节点 的父辈为祖先(x) 
        tmp = father[p];
        father[p] = x;
        p = tmp;
    }
    return x;
}

//递归写法 
int find(int x){
    if(father[x] == x){
        return x;
    }   
    int y = father[x];
    father[x] = find(y);
    dist[x] += dist[y];//更新x到根节点的距离 
    return father[x];
}

//合并 
void join(int x,int y){
    int a = find(x);
    int b = find(y);
    if(a!=b){
        father[a] = b;
        dist[a] = size[b];//更新子集合的根到 父集合根 的距离 
        size[b] += size[a];//更新父亲集合的元素个数
        maxs[b] = max(maxs[a],maxs[b]);
    }
}

int main(){
    cin>>n>>m;//元素数 操作数
    init();
    char ins[20];
    setNums = n;
    for(int i=0;i<m;i++){
        int x,y;
        scanf("%s",ins);
        if(ins[0] == 'u'){
            cin>>x>>y;
            if(find(x) != find(y)){
                join(x,y);//合并 
                setNums--;//合并一次 集合数-1 
            }
        }else if(ins[0] == 's' && ins[1] == 'a'){
            cin>>x>>y;
            int fx = find(x);
            int fy = find(y);//查找是否连接 (在同一集合) 
            if(fx==fy) cout<<1<<endl;
            else cout<<0<<endl; 
        }else if(ins[0] == 'n'){
            cin>>x;
            cout<<size[find(x)]<<endl;//查询当前集合中元素的数量 
        }else if(ins[0] == 'm'){
            cin>>x;
            cout<<maxs[find(x)]<<endl;//查询当前集合中的最大值 
        }else if(ins[0] == 's' && ins[1] =='e'){
            cout<<setNums<<endl;//查询 集合总数 
        }else{
            cin>>x;
            find(x);
            cout<<dist[x]<<endl;//打印x到它的集合的根 的距离 
//          cout<<size[x]-1-dist[x]<<endl;//查询排(与根的距离)在与x同一集合中 x后的有多少人 
        }
    } 
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/fisherss/p/10536488.html