• HDU_2196 Computer (树型dp)


      纠结的问题。做了两天,还是在拜读大牛代码的情况下ac的。好好谢谢总结吧。

      诸位大牛的思路是两次dfs。前提:建树的时候按无向边从上往下建。第一次dfs是搜出一个根结点到其他结点的最长路径和次长路径(次长路径不是最长路径的子路径,也就是说不在同一条路上。)

      一个结点到其他结点的最长路径怎么得到?1、可能是从这个结点往下取到最长路径。2、可能是从这个结点的父结点上选去另一条路径。

      当情况一时:第一次dfs所得的最长路径就是要求的结果。当情况二时:第一次dfs所得的次长路径就是所求结果。

      另外,因为是无向边建树,所以第一次dfs从下往上搜,第二次dfs从上往下搜。

      具体实现:定义dp[i]表示i到其他结点的最长路径。 f[i]表示从i结点到他的子结点的最长路径 l[i]表示i到其子结点的次长路径。 dir[i]表示最长路径所在的方向,防止最长路径跟次长路径重复。

    核心代码:

    void dfs_0(int r) {
    if(f[r]) return ;
    int len = g[r].size();
    if(len == 0) return ;
    int i, max = -1, flag = -1, flag1 = -1, c;
    for(i = 0; i < len; i++) {
    c = g[r][i].c;
    dfs_0(c);
    if(f[c] + g[r][i].val > max) {
    max = f[c] + g[r][i].val;
    flag = i;
    }
    }
    f[r] = max;
    dir[r] = flag;
    max = -1;
    for(i = 0; i < len; i++) {
    c = g[r][i].c;
    if(f[c] + g[r][i].val > max && i != flag) {
    max = f[c] + g[r][i].val;
    flag1 = i;
    }
    }
    if(flag1 != -1) l[r] = max;
    }

    void dfs_1(int r) {
    int i, len, c;
    len = g[r].size();
    for(i = 0; i < len; i++) {
    c = g[r][i].c;
    if(i == dir[r])
    dp[c] = max(dp[r], l[r]) + g[r][i].val;
    else
    dp[c] = max(dp[r], f[r]) + g[r][i].val;
    dfs_1(c);
    }
    }

    ps:因为可能出现整颗树只有一条边的情况,所以输出结果时取f[i] 和dp[i]的最大。

  • 相关阅读:
    896. Monotonic Array单调数组
    865. Smallest Subtree with all the Deepest Nodes 有最深节点的最小子树
    489. Robot Room Cleaner扫地机器人
    JavaFX
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
  • 原文地址:https://www.cnblogs.com/vongang/p/2315859.html
Copyright © 2020-2023  润新知