SCOI2017原题
其实只是D1T1,但是……bzoj的那个标签是什么鬼?
现在bzoj没有标签了……
dfs序 + 线段树?
是不是有点太麻烦了
想一个简单的做法!
长链剖分!
当然这个长是广义上的长,我们以点权作为深度,记录一个点到叶子节点的最长距离,同时也以此作为剖分的条件,取代了一般的size,然后贪心,把所有剖出来的链,放进一个堆,或者说排序也可以,连续取最大的k个加起来即可,注意答案会爆int
#include <bits/stdc++.h>
using namespace std;
const int maxn = 300000 + 100;
inline int read() {
int ch, x = 0, f = 1;ch = getchar();
while((ch < '0' || ch > '9') && ch != '-') ch = getchar();
ch == '-' ? f = -1, ch = getchar() : 0;
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return f * x;
}
int n, m;
int val[maxn];
struct Edge {
int to, nxt;
Edge() {}
Edge(int _to, int _nxt):to(_to), nxt(_nxt) {}
}E[maxn << 1];
priority_queue<long long>Q;
int fa[maxn], son[maxn], top[maxn], h[maxn], cnt;
long long max_dep[maxn];
inline void add_edge(int u, int v) {
E[++cnt] = Edge(v, h[u]), h[u] = cnt;
E[++cnt] = Edge(u, h[v]), h[v] = cnt;
}
long long ans;
void dfs1(int x) {
max_dep[x] = val[x]; son[x] = 0;
for(int i = h[x]; ~i; i = E[i].nxt) {
int to = E[i].to;
if(to == fa[x]) continue;
fa[to] = x;
dfs1(to);
max_dep[x] = max(max_dep[x], max_dep[to] + val[x]);
if(max_dep[to] > max_dep[son[x]]) son[x] = to;
}
}
void dfs2(int x) {
if(x == son[fa[x]]) top[x] = top[fa[x]];
else top[x] = x;
if(son[x]) dfs2(son[x]);
for(int i = h[x]; ~i; i = E[i].nxt) {
int to = E[i].to;
if(to == son[x] || to == fa[x]) continue;
dfs2(to);
}
}
signed main() {
memset(h, -1, sizeof(h));
n = read(), m = read();
for(int i = 1; i <= n; i++) val[i] = read();
for(int i = 1; i < n; i++) add_edge(read(), read());
dfs1(1);
dfs2(1);
for(int i = 1; i <= n;i ++) {
if(top[i] == i) Q.push(max_dep[i]);
}
int j = 1;
while(!Q.empty() && j <= m)
{
ans += Q.top();
Q.pop();
j++;
}
printf("%lld\n", ans);
return 0;
}