树形DP——1272重建道路

树形DP——1272重建道路

传送门

大佬的题解

这个题目dp【i】【j】代表以 i 这个节点为根节点的子树包含 j 个节点(包括 i 这个节点)总共要删去多少边。其中这里的dp转移式子是dp【u】【j】 = min(dp【u】【j-k】+dp【v】【k】-1)这里为什么要-1呢因为初始化的时候是用出度来优化dp【i】【1】,然后转移的时候加入了以v为根的子树的最优结果。但如果必须要u和v这条边,所以最后会-1.

 

 

同时为什么这里是从sum开始倒着遍历,如果是正着遍历,那么后面的dp【u】【j-k】就会用到之前更新的数据。那为什么不能用之前更新的数据呢。因为在之前更新是算入了加入了v这个子树的结果,如果再算加入一遍v这个节点的子树那肯定重复错误了

 

当时我错的另外一个如果选择的节点不是根节点要+1,这里是因为我们算dp【i】【j】的时候是只考虑了以i这个节点为根节点的情况,但是其实如果不是根节点。i 还会和自己的父亲连接,那么就需要多断掉 i 和 i 的父亲的节点的边,那么答案要加1.

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;
const int MAXN = 150+10;
struct Edge{
    int v, next;
}edge[MAXN];
int head[MAXN];
int cnt;
void addEdge(int u, int v)
{
    edge[cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
    return;
}

int outDegree[MAXN], inDegree[MAXN];
int dp[MAXN][MAXN];
void ini(int n)
{
    for(int i = 1; i <= n; i++)
        head[i] = -1;
    for(int i = 1; i < MAXN; i++)
        for(int j = 1; j < MAXN; j++)
            dp[i][j] = MAXN;  
    cnt = 0;
    return;
}

int dfs(int u)
{
    int temp;int sum = 1;
    for(int i = head[u]; ~i; i = edge[i].next)
    {
        int v = edge[i].v;
        temp = dfs(v); sum += temp;
        for(int j = sum; j >= 1; j--)
        {
            for(int k = 1;  k < j; k++)
                dp[u][j] = min(dp[u][j], dp[u][j-k]+dp[v][k]-1);
        }
    }
    return sum;
}

int main()
{
    int n, p;
    scanf("%d %d", &n, &p);
    ini(n);
    int u, v;
    int root;
    for(int i = 1; i < n; i++)
    {
        scanf("%d %d", &u, &v);
        addEdge(u, v);
        outDegree[u]++;
        inDegree[v]++;
    } 
    for(int i = 1; i <= n; i++)
        if(inDegree[i] == 0)
            root = i;
    for(int i = 1; i <= n; i++)
        dp[i][1] = outDegree[i];
    dfs(root);
    int ans = dp[root][p];
    for(int i = 1; i <= n; i++)
    {
        if(dp[i][p] < ans)
        {
            ans = dp[i][p];
            ans++;    
        } 
    }
    cout << ans;
    return 0;
}

 

posted @ 2021-03-13 16:23  斌斌翻水水  阅读(42)  评论(0)    收藏  举报