第十一届蓝桥杯第一场 B组 C/C++ 试题 J: 网络分析(25分)

文章描述了一种在处理连通块合并和差值计算问题时,利用带权并查集的数据结构来简化维护的方法。通过非连通块合并更新d值,以及在祖先点修改值,最终输出每个点到其根节点的差值加根节点自身值。
摘要由CSDN通过智能技术生成

在这里插入图片描述
【样例输入】

4 8 
1 1 2 
2 1 10 
2 3 5 
1 4 1 
2 2 2 
1 1 2 
1 2 4 
2 2 1 

【样例输出】

 13 13 5 3

在这里插入图片描述

看到这种合并题,第一反应应该就是dsu啊?那我们考虑怎么搞并查集,普通并查集显然8太行(或者维护起来很麻烦),观察性质可以知道,我们只需要维护当前点p及其当前点p的root的差值就可以了。那就好办了啊,带权并查集直接上啊,所以每个点最后的结果就是它与它祖先root的差值+root自身的值就可以了。

我们对于操作1,那就是非连通块的话合并并且更新其d值,已经是连通块就continue掉。

我们对于操作2,其实意思就是在他祖先点进行修改就可以了,因为我们要求的最终结果是祖先自己的值+该点与祖先的差值。
#include<bits/stdc++.h>
#define ll long long
const int maxn = 1e4 + 5;
int fa[maxn], d[maxn], now[maxn], n, m;
int find(int x) {
    if (x != fa[x]) {
        int temp = fa[x];
        fa[x] = find(fa[x]);
        d[x] += d[temp];
    }
    return fa[x];
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) fa[i] = i;
    while (m--) {
        int op; scanf("%d", &op);
        if (op == 1) {
            int a, b; scanf("%d%d", &a, &b);
            int eu = find(a), ev = find(b);
            if (eu != ev) {
                fa[ev] = eu;
                d[ev] = now[ev] - now[eu];
            }
        }
        else {
            int p, t; scanf("%d%d", &p, &t);
            int rt = find(p);
            now[rt] += t;
        }
    }
    for(int i= 1;i <= n;++i) {
        printf("%d ", now[find(i)] + d[i]);
    }
    puts("");
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值