「HDU-2196」Computer

树形dp,树的最长路径(最远点对)

题意

给出一棵nn个结点的无根树,求出每个结点所能到达的最远点的距离。

解法

将无根树转成有根树,并进行两次DFS。

  1. 第一次DFS求出每个结点在其子树中的正向最大距离正向次大距离,记为dp[0][x]dp[1][x],并标记最长距离所对应的子结点id[i] ,利用id[i]能跳过最大点计算第二大的点;

    此时可知对于每个结点ii,最远点的距离只有两种可能:

    • 结点\(i\)的正向最大距离
    • 结点\(i\)链接其父结点所能到达的最大距离,即反向最大距离
  2. 第二次DFS求出反向最长距离

    • 由上步我们获得了正向最大距离,正向次大距离和最大距离的儿子节点标记。画图可以知道我们建立的这棵树,i节点的最远距离只有两种选择:i节点所在子树的最大距离,或者i节点连接它的父节点所能到达的最大距离。(即前者往下走,后者先往上走之后很可能也往下走)
    • 所以我们只要求出*反向最大距离*dist[i][2](即i节点往它的父节点走所能到达的最大距离)就可以知道i节点在整个树中能走的最大距离了。
    • dist[i][2]求法:i节点往它的父节j点走,如果它的父节点的正向最大距离不经过i的话,那么dist[i][2]要不就是它父节点的反向最大距离+W[i][j]要不就是它父节点的正向最大距离+ W[i][j].
    • 如果它的父节点的正向最大距离经过i的话,那么dist[i][2]要不就是它父节点的反向最大距离+W[i][j]要不就是它父节点的正向次大距离+ W[i][j].
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 100;
int n, dp[3][N], id[N];
vector<int>p[N], val[N];
void dfs1(int x, int f) { //第一个dfs更新子树的最大跟次大和s
for (int i = 0; i < p[x].size(); i++) {
int to = p[x][i];
if (to == f) continue;
dfs1(to, x);
if (dp[0][x] < dp[0][to] + val[x][i]) { //这里是更新最大和,记住经过哪个儿子最大
dp[0][x] = dp[0][to] + val[x][i];
id[x] = to;
}
}
for (int i = 0; i < p[x].size(); i++) {
int to = p[x][i];
if (to == f) continue;
if (id[x] == to) continue; //跳过这个儿子,再剩下点里面找一个最大的,就是这个点次大的
dp[1][x] = max(dp[1][x], dp[0][to] + val[x][i]);
}
}
void dfs2(int x, int f) { //这个是更新先往父亲节点走一步的最大和
for (int i = 0; i < p[x].size(); i++) {
int to = p[x][i];
if (to == f) continue;
if (to == id[x]) //难点,每个父亲都有两种方式,一个是再往父亲走一步,一个是走父亲的子树,max(dp[2][x], dp[1][x]),这个就体现出这两部了,注意经不经过这个点直接走子树最大和的那个点
dp[2][to] = max(dp[2][x], dp[1][x]) + val[x][i]; //这个是针对儿子,所以是dp[2][to] = ,体现了先走一步父亲,经过就走次大的,再走最大的就重复了一段
else
dp[2][to] = max(dp[2][x], dp[0][x]) + val[x][i];
dfs2(to, x); //因为dfs1更新了所有子树的特点,子树的信息可以直接用了,父节点的信息从一步步dfs下去都已经更新好了,上面的也是可以直接用,每一步都看看是不是走父亲的父亲更好,一直更新最优
}
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
while (cin >> n) {
memset(dp, 0, sizeof dp);
for (int i = 0; i <= n; ++i)val[i].clear(), p[i].clear();
for (int i = 2; i <= n; ++i) {
int a, b; cin >> a >> b;
p[i].push_back(a);
val[i].push_back(b);
p[a].push_back(i);
val[a].push_back(b);
}
dfs1(1, -1);
dfs2(1, -1);
for (int i = 1; i <= n; ++i)
cout << max(dp[0][i], dp[2][i]) << endl;
}
}

「HDU-2196」Computer (树形DP、树的直径)的更多相关文章

  1. 【HDU 2196】 Computer (树形DP)

    [HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...

  2. HDU 2196.Computer 树形dp 树的直径

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. computer(树形dp || 树的直径)

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  4. hdu 2196(Computer 树形dp)

    A school bought the first computer some time ago(so this computer's id is 1). During the recent year ...

  5. hdu-2169 Computer(树形dp+树的直径)

    题目链接: Computer Time Limit: 1000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) ...

  6. Computer(HDU2196+树形dp+树的直径)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196 题目: 题意:有n台电脑,每台电脑连接其他电脑,第i行(包括第一行的n)连接u,长度为w,问你每 ...

  7. hdu 4607 树形dp 树的直径

    题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n)个点,至少需要走多少距离(每条边的距离是1): 思路:树形dp求树的直径r: a:若k<=r+1 ...

  8. POJ 3162.Walking Race 树形dp 树的直径

    Walking Race Time Limit: 10000MS   Memory Limit: 131072K Total Submissions: 4123   Accepted: 1029 Ca ...

  9. VIJOS1476旅游规划[树形DP 树的直径]

    描述 W市的交通规划出现了重大问题,市政府下决心在全市的各大交通路口安排交通疏导员来疏导密集的车流.但由于人员不足,W市市长决定只在最需要安排人员的路口安放人员.具体说来,W市的交通网络十分简单,它包 ...

  10. poj3162 树形dp|树的直径 + 双单调队列|线段树,好题啊

    题解链接:https://blog.csdn.net/shiqi_614/article/details/8105149 用树形dp是超时的,, /* 先求出每个点可以跑的最长距离dp[i][0|1] ...

随机推荐

  1. 从零开始的 dbt 入门教程 (dbt-core 基础篇)

    最近一直在处理数据分析和数据建模的事情,所以接触了 dbt 等数据分析的工具,国内目前对于 dbt 比较详细的资料不多,所以打算写四道五篇 dbt 相关的文章,本文属于 dbt 系列的第一篇,本篇主要 ...

  2. 网安靶场环境_DVWA-读取文件报错File not found! Cookie中有两个security键

    DVWA-文件包含漏洞-读取文件报错-ERROR: File not found! Cookie中有两个security键 1 问题复现 (1)登录DVMA后,设置DVWA Security为Low. ...

  3. ETL-txt数据转换为Excel数据

    前言:   将txt文件中的数据抽取出来,然后装载到Excel中. 具体操作步骤:   数据准备 id,name,age,gender,province,city,region,phone,birth ...

  4. [CF1748F] Circular Xor Reversal

    题目描述 You have an array $ a_0, a_1, \ldots, a_{n-1} $ of length $ n $ . Initially, $ a_i = 2^i $ for ...

  5. LCIS最长公共上升子序列!HDU-1423

    This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence ...

  6. apache+mysql+php环境安装及配置

    一.安装mysql 1.yum安装mysql # yum -y install mysql mysql-server 2.安装mariadb,用mariadb来启动数据库,systemctl star ...

  7. 面向对象(OOP)

    面向对象 面向对象 面向过程 & 面向对象 面向过程思想 步骤清晰简单,第一步做什么,第二步做什么... 面对过程适合处理一些较为简单问题 面向对象思想 物以类聚,分类的思维模式,思考问题首先 ...

  8. 真的最后一次了——城院GO导航大作业迭代最终版

    真的!!!最后一次了!不骗人! 1.小程序的体验版二维码: 想体验的可以申请一下体验权限: 2.小程序目前功能介绍 1.首先进入是index页面:点击第一个是学校简介页面,第二个能直接跳到主程序的地图 ...

  9. Python——第一章:循环语句while

    循环语句可以让我们的代码重复的去执行 while循环: while 条件:        代码 过程: 判断while循环的条件是否为真, 如果真, 执行代码. 然后再次判断条件.....直到条件为假 ...

  10. 防火墙配置SNMP

    深信服AC配置SNMP 深信服AF配置SNMP 深信服AD配置SNMP 在接口上启用是snmp管理,平台有网神的mib,可以都读到数据