Hekyのblog

洛谷 P1272 重建道路

url: https://www.luogu.com.cn/problem/P1272

tag:
动态规划,树形DP

思路:
简单的树形DP和背包结合。令 f[u][j] 表示以u节点为根的子树在需要取出j个节点时最少需要断的边。最后在输出答案的时候在所有节点中选择一个答案最小的,注意选择其他节点为根节点时需要断去父节点和其之间的一条边。最后输出答案即可。

代码:

#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
using namespace std;  
const int N = 200;  
int h[N], e[N * 2], ne[N * 2], idx;  
int s[N];  
int n, p;  
int f[N][N];  
void add(int a, int b)  
{  
    e[idx] = b;  
    ne[idx] = h[a];  
    h[a] = idx ++;  
}  
void dfs(int u, int fa)  
{  
    s[u] = 1;  
    f[u][1] = 0;  
    for (int i = h[u]; ~i; i = ne[i])  
    {  
        int v = e[i];  
        if (v == fa) continue;  
        dfs(v, u);  
        s[u] += s[v];  
        for (int j = min(s[u], p); j >= 0; j --)  
        {  
            f[u][j] += 1;  
            for (int k = 0; k <= min(j, s[v]); k++)  
                f[u][j] = min(f[u][j], f[u][j - k] + f[v][k]);  
        }  
    }  
}  
int main()  
{  
    memset(h, -1, sizeof h);  
    memset(f, 0x3f, sizeof f);  
    cin >> n >> p;  
    for (int i = 0; i < n - 1; i ++)  
    {  
        int a, b;  
        cin >> a >> b;  
        add(a, b), add(b, a);  
    }  
    dfs(1, 0);  
    int res = f[1][p];  
    for (int i = 2; i <= n; i ++) res = min(res, f[i][p] + 1);  
    cout << res << endl;  
    return 0;  
}

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »