[Acwing蓝桥杯DP] 2069. 网络分析
题目描述:
给出一个 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!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】