「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. dbeaver软件的使用

    dbeaver软件的使用 一.dbeaver简介: dbeaver是免费和开源(GPL)为开发人员和数据库管理员通用数据库工具. DBeaver [1] 是一个通用的数据库管理工具和 SQL 客户端, ...

  2. linux debian安装erlang和rabbitmq

    debian系安装rabbitmq的服务端 安装erlang 本文讲rabbitmq. erlang语言环境就root快捷安装,方便学习(erlang版本23.x) apt install erlan ...

  3. Android 实现APP可切换多语言

    原文: Android 实现APP可切换多语言 - Stars-One的杂货小窝 如果是单独给app加上国际化,其实很容易,创建对应的国家资源文件夹即可,如values-en,values-pt,ap ...

  4. Element的安装与基本使用

    一.什么是Element? Element是饿了么团队研发的一套为开发者与设计师等准备的基于Vue2.0的桌面端组件库,使开发人员可以快速拼凑出一套页面 组件:组成网页的部件,例如:超链接,按钮,图片 ...

  5. 在 Sealos 中使用区块链技术实现统一支付系统

    拿着区块链技术不一定是去发币,很多业务系统也适合用这些技术,比如做个统一支付系统,积分系统等,可以做为一家公司的金融基础设施,或支付中台.拿链的技术去做有很多好处: 高可用,自带多区域高一致性的能力, ...

  6. 使用axios发送请求的几种方式

    1.是什么? axios 它的底层是用了 XMLHttpRequest(xhr)方式发送请求和接收响应,xhr 相对于之前讲过的 fetch api 来说,功能更强大,但由于是比较老的 api,不支持 ...

  7. SLR(1)分析法

    由于LR(0)的能力实在是太弱了.例如: I = { X=>α·bβ, A=>α·, B=>α· } 这时候就存在两个冲突. 1.移进和规约的冲突: 2.规约和规约的冲突. SLR( ...

  8. python tkinter 使用(六)

    python tkinter 使用(六) 本文主要讲述tkinter中进度条的使用. 1:确定的进度条 progressbar = tkinter.ttk.Progressbar(root, mode ...

  9. ElasticSearch之Delete index API

    删除指定的索引. 同时删除索引关联的数据.分片.元数据等相关的资源,因此执行前需要慎重. 命令样例如下: curl -X DELETE "https://localhost:9200/tes ...

  10. 5.elasticsearch中查询条件

    目录 一.URI查询 指定字段.泛查询 分组和phrase Bool条件 must条件 范围查询 通配符查询 正则表达式 模糊匹配与近似查询 二.RequestBody&DSL ignore_ ...