1. 程式人生 > >bzoj 3252 攻略(長鏈剖分 + 貪心)

bzoj 3252 攻略(長鏈剖分 + 貪心)

#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;
}