• 树形dp compare E


     
    题目大意:给你一棵树,让你放最少的东西来覆盖所有的边
     
    这个题目之前写过,就是一个简单的树形dp的板题,因为这个每一个节点都需要挺好处理的。
    这个树形dp是从底往根部来递推,所以每一个点,都是由它的根节点来递推的。
    如果一个根节点的子节点放了东西,那么这个根节点就可以有选择,但是如果没有放东西,那么这个根节点就必须放东西。
     

    题目大意:给你一棵树,让你用最小的东西来覆盖所有的点。

    这个题目和上面那个很像,但是有点不太一样,如果是覆盖所有的点,就不一点要覆盖所有的边,但是如果覆盖了所有的边就肯定会覆盖所有的点。

    那么这个题目应该怎么考虑呢,这个同样是一个树形dp,每一个点都是由它的子节点推过来的。

    这个就和上面那个有一点不太一样,但是很像。

    上面那个对于每一个根节点,只要有一个子节点没有放东西,那么这个根节点肯定要放东西。

    而这个题目就不太一样,对于每一个节点,如果想要被覆盖,那么有三种可能,一个是它本身放了东西,一个是它的父节点放了东西,一个是它的子节点放了东西。

    所以这个dp对于每一个节点就可以有三种状态。

    dp[cur][0]表示这个点被放了东西

    dp[cur][1]表示这个点的子节点被放了东西。

    dp[cur][2]表示这个点的父节点被放了东西

    状态定义好了,这个转移方程就比较好写了。

    dp[cur][0]=min(dp[x][0],dp[x][1],dp[x][2])     如果它被放了东西,那么它的子节点就肯定已经被覆盖了

    dp[cur][1]=min(dp[x][0],dp[x][1])    这个为什么没有dp[x][2]因为我们已经确定cur这个节点不会放东西。

    dp[cur][2]=min(dp[x][0],dp[x][1])    为什么这个dp[x][2]没有呢,理由同上。

    但是这个还有一点点小问题要注意

    第一个就是dp[cur][0]=1 因为这个点被放了东西,所以要+1

    但是dp[cur][1]不需要给她初值1 因为它是由它的子节点推过来 而子节点已经被赋值过了。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn = 1e4 + 100;
    int dp[maxn][4];
    vector<int>G[maxn];
    
    void dfs(int u,int pre)
    {
    //    printf("www dp[%d][0]=%d dp[%d][1]=%d dp[%d][2]=%d
    ", u, dp[u][0], u, dp[u][1], u, dp[u][2]);
        bool ok = false;
        int dif = inf;
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i];
            if (v == pre) continue;
            dfs(v, u);
        }
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i];
            if (v == pre) continue;
            dp[u][0] += min(min(dp[v][1], dp[v][0]), dp[v][2]);
            dp[u][2] += min(dp[v][1], dp[v][0]);
            dif = min(dif, abs(dp[v][1] - dp[v][0]));
            if(dp[v][0]<dp[v][1])
            {
                ok = true;
                dp[u][1] += dp[v][0];
            }
            else dp[u][1] += dp[v][1];
        }
        if (!ok) dp[u][1] += dif;
        //printf("dp[%d][0]=%d dp[%d][1]=%d dp[%d][2]=%d
    ", u, dp[u][0], u, dp[u][1], u, dp[u][2]);
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i=1;i<n;i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for (int i = 1; i <= n; i++) dp[i][0] = 1;
        dfs(1, -1);
        printf("%d
    ", min(dp[1][0], dp[1][1]));
        return 0;
    }
    树形dp
  • 相关阅读:
    jsp小测文件上传+servlet+分页 47/32(继续努力!)
    使用分层实现业务处理
    jsp 2018年5月7日11:04:15题库52/34
    jsp题库 (一)小测(25/21)
    Js2云题库,好题就得藏起来
    Jsp前2纠错
    【转】js限制用户上传文件类型
    【转】HTML from enctype 定义和实例
    fmt jstl标签 时间格式化例子
    【转】hibernate中lazy的使用
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11009125.html
Copyright © 2020-2023  润新知