zoukankan      html  css  js  c++  java
  • 一道简单树形dp

    题意:给定一棵树,从中选出一些节点,使得不成父子关系的节点对数最多。问这个最大值是多少。

    思路:首先既然是给定一颗树,先要选择合适的数据结构,来保存这颗树。由于这颗树只关心根节点在哪里,所以只需要用一个fa数组来保存每个点的根节点,此外设初始化为0,所以根节点的fa[root]为0,所以从任意一个结点的父节点往上遍历,直到遍历到某某个结点的父节点为0,则这个结点就是父节点

    这道题个人感觉关键是从根节点开始往下dp,所以根节点要确定..

    这道题的状态转移方程为,dp[i][1],选用第i个节点时,所能得到的最大对数,dp[i][0]不选用第i个节点时所能得到的最大对数,dp[i][0]=求和max(dp[j][0],dp[j][1]);dp[i][1]=求和dp[j][0].所以每一个父节点都依赖于它的子节点。所以递归求每一个子节点的dp[j]的值,最后在累加到dp[i]上,而边界条件是,递归到叶子节点时,dp[i][0]=0,dp[i][1]=1;加上代码

    int n;  // 结点个数
    int dp[maxn][2];  // dp[i][0] 表示不选择结点 i,dp[i][1] 表示选择结点 i
    int father[maxn];  // father 记录了结点的父结点编号
    
    void tree_dp(int node) {
        dp[node][0] = 0;
        dp[node][1] = 1for(int i = 1; i <= n; i++) {
            if(father[i] == node) {  // i 为 node 的子结点
                tree_dp(i);  // 递归计算子结点
                // 关键
                dp[node][1] += dp[i][0];  // 选择父结点,则必须不选择子结点
                dp[node][0] += max(dp[i][1], dp[i][0]);  // 不选择父结点,则可以选择或不选择子结点
            }
        }
    }
    
    int main() {
        int f, c, root;
        scanf("%d", &n);
        memset(father, 0, sizeof(father));
        memset(visited, 0, sizeof(visited));
        root = 0;  // 记录树的根结点
        while (scanf("%d %d", &c, &f), c || f) {  // 读入父子关系,前一个结点是后一个结点的孩子
            father[c] = f;
            root = f;
        }
        while(father[root]) {  // 查找根结点
            root = father[root];
        }
        tree_dp(root);  // 从根结点出发进行动态规划
        printf("%d
    ", max(dp[root][0], dp[root][1]));  // 求出最终答案,根可以选或不选
        return 0;
    }
  • 相关阅读:
    iOS 3DTouch 的开发套路大全
    启动图后面 添加有倒计时的广告图
    激光推送报错:APNs is not available,please check your provisioning profile and certification 和 设置别名问题 app not registed, give up set tag:
    iOS 微信和支付宝关于回调处理
    Android 开机自启动应用
    android快捷键
    如何让Eclipse的智能提示像VS一样霸气
    Win7下Eclipse中文字体太小
    Android的SharedPreferences实用技巧
    Java基础知识总结
  • 原文地址:https://www.cnblogs.com/rainyskywx/p/10397807.html
Copyright © 2011-2022 走看看