luogu P4657 [CEOI2017]Chase

https://www.luogu.com.cn/problem/P4657

我们可以直接考虑贡献

逃亡者碰到过的铁球追随者一定会碰到
直接考虑追随者会多碰到的铁球即可

对于一条路径,如果在起始点放一个磁铁,那么它的贡献是周围一圈的点

如果在其他点放磁铁,那么它的贡献是周围一圈的点减去上一个点的权值

于是我们考虑DP

f [ u ] [ i ] f[u][i] f[u][i]表示从 u u u子树中的某个点出发(包括 u u u),最后到达 u u u的最大路径

g [ v ] [ i ] g[v][i] g[v][i]表示从 v v v出发,到达 v v v子树中某个点的最大路径

然后答案就是类似max卷积一样

正反都跑一次转移即可

code:

#include<bits/stdc++.h>
#define N 200050
#define ll long long
using namespace std;
struct edge {
    int v, nxt; 
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v) {
    e[eid].v = v;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
int n, m, a[N], sta[N];
ll f[N][105], g[N][105], s[N], ans = 0;
void dfs(int u, int fa) {
    for(int i = 1; i <= m; i ++) f[u][i] = s[u], g[u][i] = s[u] - a[fa];
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v;
        if(v == fa) continue;
        dfs(v, u);
        for(int j = 0; j <= m; j ++) ans = max(ans, f[u][j] + g[v][m - j]);
        
        for(int j = 1; j <= m; j ++) {
            f[u][j] = max(f[u][j], max(f[v][j], f[v][j - 1] + s[u] - a[v]));
            g[u][j] = max(g[u][j], max(g[v][j], g[v][j - 1] + s[u] - a[fa]));
        }
    }
    int top = 0;
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v;
        if(v == fa) continue;
        sta[++ top] = v;
    }

    for(int i = 1; i <= m; i ++) f[u][i] = s[u], g[u][i] = s[u] - a[fa];
    for(int i = top; i >= 1; i --) {
        int v = sta[i];
        for(int j = 0; j <= m; j ++) ans = max(ans, f[u][j] + g[v][m - j]);
        for(int j = 1; j <= m; j ++) {
            f[u][j] = max(f[u][j], max(f[v][j], f[v][j - 1] + s[u] - a[v]));
            g[u][j] = max(g[u][j], max(g[v][j], g[v][j - 1] + s[u] - a[fa]));
        }
    }
}
int main() {
    init();
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    for(int i = 1; i < n; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        insert(u, v), insert(v, u);
        s[u] += a[v], s[v] += a[u];
    }

    dfs(1, 0);
    printf("%lld", ans);
    return 0;
}

posted @ 2021-11-10 07:33  lahlah  阅读(73)  评论(0编辑  收藏  举报