[codeforces856D]Masha and Cactus

题目大意

给定n个点的树,接下来给出m条非树边,每条非树边有一个价值。现在你可以添加一些非树边,在保证每个点最多在一个简单环的情况下,求价值和最大值。

n,m≤200000

分析

首先考虑dp,设f[i]表示以i为根的子树的答案。
把每条非树边挂在lca上。求f[i]时,首先处理不选择一条lca为i的情况。接下来枚举一条lca=i的非树边,加上其它儿子的f值、该边所覆盖的路径的答案。
难点就在于求一条路径覆盖后的答案。一个想法是:每做完一棵子树后,给子树内所有节点都加上i到其父亲对答案造成的影响。用数据结构维护。

但是有更好的方法。由于上面对答案的更新是自下往上的。可以考虑用并查集路径压缩。设g[i]表示点i到已经压缩的到祖先的一条路径上的答案。每做完一棵子树就给它的所有直接儿子都加上相应的值,并压缩它们到父亲的路径。查询时在getfather的时候更新g数组即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

#define psb push_back

using namespace std;

const int N=2e5+5,Log=18;

typedef long long LL;

int n,m,h[N],nxt[N],f[N],g[N],fa[N],s[N]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值