zoukankan      html  css  js  c++  java
  • 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]的最大。

  • 相关阅读:
    SQL大语句——实现分页,select top后面跟变量出错
    jQuery异步请求(如getJSON)跨域解决方案
    Debug常用命令
    清华操作系统实验--80x86汇编基础
    在Windows10中运行debug程序
    恢复Windows10应用商店
    最少硬币问题
    嵌套矩形问题
    清华大学操作系统实验准备--挖坑
    动态规划入门-数字三角形
  • 原文地址:https://www.cnblogs.com/vongang/p/2315859.html
Copyright © 2011-2022 走看看