[Acwing蓝桥杯DP] 2069. 网络分析

题目链接:2069. 网络分析 - AcWing题库

题目描述:
给出一个 n 个孤立点的图,每个点上的权值都是 0,进行 m 次操作
操作 1 :把两个点所在的连通块合并起来
操作 2 :向某个点所在的连通块的所有点累加一个值
最后输出每个点上的权值

数据范围:1<=n<=1e4

                  1<=m<=1e5

分析:复杂并查集 树上差分
这个题不但要将点连起来,还要求每个点上的权值;

注意:每次操作是有先后顺序的,如果以前都已经连在一块了,再次连入时候,不加原来的值

难点:1、每个点的权值为该点到根节点的路径上权值的和距离

           2、优化路径 d[x]+=d[p[x]] ;

    int r=find(p[x]);//这一步调用的find函数返回后别忘了执行后面的语句
    d[x]+=d[p[x]];//看不懂就根据手动模拟一下样例
    p[x]=r;//直接赋值p[x]=根节点,下次再想找x的父节点就不用花大量时间遍历了,p数组里存的就是

           3、将一个树A与另一个树B合并

          将A接在B后边 要将A的根结点的权值减去B的根结点权值,避免重复计算,防止1的定义错乱

代码如下:

复制代码
#include <bits/stdc++.h>

using namespace std;

const int N=1e4+10;

int n,m;
int p[N],d[N];

int find(int x)
{
    if(x==p[x]||p[p[x]]==p[x])return p[x];
    int r=find(p[x]);
    d[x]+=d[p[x]];
    p[x]=r;
    return r;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)p[i]=i;
    while(m--)
    {
        int t,a,b;
        scanf("%d%d%d",&t,&a,&b);
        if(t==1)
        {
            a=find(a),b=find(b);
            if(a!=b)
            {
                d[a]-=d[b];
                p[a]=b;   
            }
        }else
        {
            a=find(a);
            d[a]+=b;
        }
    }
    
    for(int i=1;i<=n;i++)
    {
        if(find(i)==i)printf("%d ",d[i]);
        else printf("%d ",d[i]+d[p[i]]);
    }
    
    return 0;
}
复制代码

 

END!!!

 

posted @   秦末  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
1 博文导航目录
点击右上角即可分享
微信分享提示