「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. 京东广告研发近期入选国际顶会文章系列导读——CIKM 2023篇

    近年来,放眼业界广告推荐领域的算法获得了长足的发展,从几篇奠定基础的序列学习.大规模图学习.在线学习&增强学习.多模态推荐问题等起步,业内算法不断迭代发展并在学术和工业场景上取得不错的应用. ...

  2. 时间复杂度为 O(n^2) 的排序算法

    对于小规模数据,我们可以选用时间复杂度为 O(n2) 的排序算法.因为时间复杂度并不代表实际代码的执行时间,它省去了低阶.系数和常数,仅代表的增长趋势,所以在小规模数据情况下, O(n2) 的排序算法 ...

  3. Socket编程和实现聊天室

    一.HTTP协议的socket通信 1.server.py # 服务端 import sys import socket ip_point = ('127.0.0.1',9999) sk = sock ...

  4. 封装RabbitTemplate,使用自定义消息转换器

    前面创建项目我就省了...活不多说直接上代码! 核心代码 RabbitMQConfig import lombok.extern.slf4j.Slf4j; import org.springframe ...

  5. requests.exceptions.ProxyError问题解决方法

    出现这个问题是因为你系统上在使用代理,然后你的代理又是规则匹配的. https://stackoverflow.com/questions/36906985/switch-off-proxy-in-r ...

  6. Fiddler使用 抓取手机数据包及中文乱码解决方案

    https://blog.csdn.net/zyb2017/article/details/79260086

  7. ElasticSearch之cat component templates API

    命令样例如下: curl -X GET "https://localhost:9200/_cat/component_templates?v=true&pretty" -- ...

  8. 文心一言大模型-function Calling的应用

    "大模型的函数调用"(Large Model Function Calling)是一个涉及到在大型人工智能模型,如 GPT-4 或类似的高级深度学习模型中使用函数调用的概念.在这种 ...

  9. Kiractf

    信息收集 主机发现和端口扫描只开放了80的web服务 ​​ ‍ WEB打点 访问首页有文件上传,肯定可以利用一波.language那个页面甚至文件包含都写脸上了. root@Lockly tmp/ki ...

  10. Shiro-550反序列化漏洞(CVE-2016-4437)复现

    本文章使用Shiro_exploit此工具复现,靶机环境为vulhub 项目地址: https://github.com/insightglacier/Shiro_exploit https://gi ...