题目大意
给定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]