Nowcoder 106 C.Professional Manager(统计并查集的个数)

题意:

给出四种操作:

1. 合并u,v两棵树

2. 从u所在的集合中删除u

3. 询问u所在集合有多少颗树

4. 询问 u,v是否在同一个集合

分析:

对于删除操作, 只要新开一个点代替原来的点即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5e4;
int f[maxn], cnt[maxn], id[maxn]; 
//id是负责记录这个点是原来的点还是删除操作后新开的点
void init(){
    for(int i = 0; i < maxn; i++){
        f[i] = i;
        cnt[i] = 1;
        id[i] = i;
    }
}
int find(int x){
    if(x == f[x]) return x;
    else {
        return f[x] = find(f[x]);
    }
}
void merge(int u, int v){
    int a = find(u);
    int b = find(v);
    if(a != b){
        f[b] = a;
        cnt[a] += cnt[b];
        cnt[b] = 0;
    }
}
int n, q;
int main(){
//    freopen("1.txt","r", stdin);
    ios::sync_with_stdio(false);
    int T;
    cin >> T;
    for(int kase = 1; kase <= T; kase++){
        cout << "Case #" << kase << ":\n";
        init();
        cin >> n >> q;
        int tot = n;
        for(int i = 0; i < q; i++){
            int op, u, v;
            cin >> op;
            switch(op){
                case 1:{
                    cin >> u >> v;
                    merge(id[u],id[v]);
                    break;
                }
                case 2:{//删除操作,另开一个点代替原来的点
                    cin >> u;
                    int p = find(id[u]);
                    cnt[p]--;
                    id[u] = ++tot;
//                    f[id[u]] = id[u];
                    break;
                }
                case 3:{
                    cin >> u;
                    cout << cnt[find(id[u])] << "\n";
                    break;
                }
                case 4:{
                    cin >> u >> v;
                    if(find(id[u]) == find(id[v])){
                        cout << "YES\n";
                    }else cout << "NO\n";
                }
            }
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/Jadon97/p/9007212.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值