并查集计数——总结与例题

比较基础的知识可以看这位大佬的博客 or 这篇博客
并查集主要有初始化、union、计数等

const int N = 1008;
ll fa[N];///存储父亲节点
ll sum[N];///计数
///寻找父亲节点
ll _Get_fa(int x){
    if(x == fa[x]) return x;
    else return fa[x] = _Get_fa(fa[x]);
}
///初始化:
void _Init(){
    for(int i=0;i<=N;i++){
        fa[i] = i;
        sum[i] = 1;
    }
}

其中_Find的时候一种是递归的方法,另一种是非递归的方法(路径压缩)

//将根节点设置为-1的非递归方法
int _Find(int x)
{
    int y = x;
    while(y!= -1)
        y = fa[y];
    return y;
}

合并的时候

for(int i=1;i<=m;i++){
    itn a=read,b=read;
    ll fa_a = _Get_fa(a);
    ll fa_b = _Get_fa(b);
    if(fa_a  != fa_b){
        fa[fa_b] = fa_a;///转移
        sum[fa_a] += sum[fa_b];///计数
    }
}

一个例题:
Charles and the Corgi Conundrum
时间限制: 1 Sec 内存限制: 128 MB

题目描述
Charles, the Corgi-obsessed programmer, has just found Corgi Heaven! He visits a pond with exactly n dogs in a nearby field, all of which are Corgis. He wishes to take home exactly one Corgi, and as he is not partial to any particular doggo, he selects one at random. However, we all know that Corgis are amazingly energetic and friendly creatures who share inseparable bonds with others of their kind. Thus, upon choosing an initial Corgi, Charles also has to take its friends, and then its friends’ friends, and so on…
Now given the friendships that all of the Corgis share, Charles wishes to know what the expected number of Corgis that he will take home is if he chooses an initial Corgi at random.

Given n Corgis and m friendship bonds between them, determine the number of Corgis that Charles can expect to take home, if he picks one Corgi at random.
输入
The first line contains a single, positive integer, s, which is the number of distinct scenarios to consider. For each scenario, the first line contains a two integers, n and m (1 ≤ n ≤ 1,000; 0 ≤ m ≤ 1,000), representing the number of Corgis that exist in the pond and the number of friendship bonds, respectively. The following m lines of the scenario will contain friendship bonds, if any, and consist of two integers, u and v (1 ≤ u ≤ n; 1 ≤ v ≤ n), meaning that Corgi number u and Corgi number v are friends.
输出
For each scenario, output “Pond #i: x” where i is the number of the pond (in the order of the input, starting with 1) and x is the expected number of Corgis that Charles can expect to take with him for this pond to 3 decimal places and rounded. For example, 12.1713 rounds to 12.171, 12.1715 rounds to 12.172, and 12.1718 rounds to 12.172.
样例输入

2 
4 2 
1 2 
3 4 
10 6 
1 3 
3 2 
7 5 
10 8 
4 3 
9 10

样例输出

Pond #1: 2.000 
Pond #2: 3.000

Code :

const int N = 1008;
ll fa[N];
ll sum[N];
ll _Get_fa(int x){
    if(x == fa[x]) return x;
    else return fa[x] = _Get_fa(fa[x]);
}
void _Init(){
    for(int i=0;i<=N;i++){
        fa[i] = i;
        sum[i] = 1;
    }
}
int main()
{
    ///freopen("this.out","w",stdout);
    int T = read;
    int cas = 0;
    while(T --){
        cas ++;
        _Init();
        printf("Pond #%d: ",cas);
        int n=read,m=read;
        for(int i=1;i<=m;i++){
            itn a=read,b=read;
            ll fa_a = _Get_fa(a);
            ll fa_b = _Get_fa(b);
            if(fa_a  != fa_b){
                fa[fa_b] = fa_a;
                sum[fa_a] += sum[fa_b];
                ///sum[fa_b] += sum[fa_a];
            }
        }
        ll ans = 0;
        for(int i=1;i<=n;i++){
            ///ans += sum[i];
            if(_Get_fa(i) == i){
                ans += sum[i] * sum[i];
            }
        }
        printf("%.3lf\n",1.0*ans/(1.0 * n));
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值