15pts求助,dp[i][j]表示将i子树删到只剩j个节点的最小代价
  • 板块P8564 ρars/ey
  • 楼主Edison688
  • 当前回复4
  • 已保存回复4
  • 发布时间2022/10/5 11:35
  • 上次更新2023/10/27 08:44:09
查看原帖
15pts求助,dp[i][j]表示将i子树删到只剩j个节点的最小代价
374109
Edison688楼主2022/10/5 11:35
#include <cstring>
#include <iostream>

typedef long long LL;

using namespace std;

const int N = 510;
const LL INF = 0x3f3f3f3f3f3f3f3f;

int n, f[N], sz[N];
LL dp[N][N];

int h[N], ne[N], e[N], idx;
void add(int a, int b)
{
    idx ++ ;
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
}

int dfs1(int u, int p)//求 sz;
{
    sz[u] = 1;
    for (int i = h[u]; i; i = ne[i])
    {
        int v = e[i];
        if (v == p) continue;
        sz[u] += dfs1(v, u);
    }
    return sz[u];
}

void dfs2(int u, int p)//求 dp;
{
    int cnt = 0,sum = 0;
    for (int i = h[u]; i; i = ne[i])
    {
        int v = e[i];
        if (v == p) continue;
        dfs2(v, u);
        cnt ++ ;
        sum += dp[v][1];
    }
    
    dp[u][sz[u]] = 0;
    dp[u][cnt + 1] = sum;
    for (int i = h[u]; i; i = ne[i])
    {
        int v = e[i];
        if (v == p) continue;
        for (int j = sz[u]; j > cnt; j -- )
            for (int k = 2; k <= sz[v]; k ++ )
                dp[u][j] = min(dp[u][j], dp[u][j - k] + dp[v][k]);
    }
    
    dp[u][1] = f[sz[u]];
    for(int i = 2; i <= sz[u]; i ++ )
        dp[u][1] = min(dp[u][1], dp[u][i] + f[i]);
    
}

int main()
{
    cin >> n;
    for (int i = 2; i <= n; i ++ ) cin >> f[i];
    for (int i = 1; i < n; i ++ )
    {
        int u, v;
        cin >> u >> v;
        add(u, v), add(v, u);
    }
    dfs1(1, -1);
    memset(dp, 0x3f, sizeof dp);
    dfs2(1, -1);
    cout << dp[1][1] << endl;
    return 0;
}
2022/10/5 11:35
加载中...