带权并查集

 题解:   一道带权并查集,就是并查集的模板,但是需要一点小细节,首先要给每一条边都给上一个值,然后合并的时候一点点累加,比如x和y合并 x在y的上面所以需要合并就是两个的总和砖块相加给当前父节点,然后就是在find的函数里的一个点,因为find要路径压缩,就是因为你要合并然后你以前的父节点和你连的那条线连到了新的父节点上所以你要记录以前的父节点然后相加在去连新父节点。

(72条消息) 带权并查集_带权并查集理解不了_syddf_shadow的博客-CSDN博客

 

  

 这个就是前面说的find那的关键点让这边有新值

int find(int x)
{
    if (x != parent[x])
    {
        int t = parent[x];
        parent[x] = find(parent[x]);
        value[x] += value[t];
    }
    return parent[x];
}

然后就是上面说的合并的时候怎么去把权值合并连上相关的线

就是搞新的线,一个父节点连到另外一个节点,这条线应该是都少,

 看上图,比如砖块例题,叠的时候x和y之间的线应该这么搞呢。

无非就是y点到父节点的砖块数就是这条线的权值了,就算是这条线代表的是x到底部砖块的个数。

 

 

然后在给这个题的代码

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define int long long
using namespace std;
const int N=1e5+5;
int fu[N];
int ans=0;
int f[N],l[N];
int find(int x)
{
    if(x==fu[x]) return x;
    else {
        int t=fu[x];
        fu[x]=find(fu[x]);
        f[x]+=f[t];
        return fu[x];
    }
}
void join(int x,int y)
{
    int fx=find(x),fy=find(y);
    if(fx!=fy)
    {
        fu[fx]=fy;
        f[fx]=l[fy];
        l[fy]+=l[fx];
    }
}
int32_t main()
{
    int q;
    cin>>q;
    char c;
    for(int i=1;i<=N;i++)
    {
        fu[i]=i;
        l[i]=1;
    }
    while (q--)
    {
        ans=0;
        int x,y;
        cin>>c>>x;
        if(c=='M')
        {
            cin>>y;
            join(x,y);
        }
        else
        {
            int k=find(x);
            cout<<f[x]<<endl;
        }
    }
    return 0;
}

 

posted @ 2023-07-21 16:54  whatdo+  阅读(15)  评论(0编辑  收藏  举报