http://acm.hdu.edu.cn/showproblem.php?pid=2196

题意:找出树中每个节点到其它点的最远距离。

题解:

  首先这是一棵树,对于节点v来说,它到达其它点的最远距离可以走两个方向,一个是向它的子节点走,不妨称作正向走;一个是向它的父节点方向,不妨称作反向走。也就是说节点v能到达的最远距离是max{正向走的最远距离,反向走的最远距离}。所以可以先dfs一次求出每个节点能正向走的最大距离。显然反向走一定会经过父节点,这时就会出现两种情况:1.父节点u正向走的最远距离经过子节点v。2.父节点u走的最远距离不经过子节点v。当经过子节点v时,显然要算v反向走的最远距离时不能走u的正向最远的那条经过自己的路径,而u的正向第二远的路径将是最优的选择。可以想想看,v反向最远当然是由u的正向最远转移过来的,这个正向最远经不经过v很关键。因此正向dfs时还要记录一个第二最远的距离。

  设dp[][3],dp[v][0]表示v正向走的最远距离,dp[v][1]表示v正向走的第二最远距离,dp[v][2]表示v反向走的最远距离。

  那么答案显然是:ans=max{dp[v][0],dp[v][2]}。

  其中:当u最远不经过v时:dp[v][2]=max{dp[u][2],dp[u][0]}+cost;

    当u最远经过v时:dp[v][2]=max{dp[u][2],dp[u][1]}+cost;

  我之前有个非常疑惑的地方就是为什么dp[v][2]的转移还要有dp[u][2]?我直接根据u经不经过v分两种情况不就是dp[v][2]了吗,怎么还要跟dp[u][2]+cost之间取个最大值?后来想想才明白,其实这也是个状态转移啊!dp[u][2]表示u反向走的最远距离,而dp[u][0],dp[u][1]都是正向走的距离,当由u推v的时候当然要从u的正向和反向之间取个最大值了!

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN=;
struct Node{
int to,cost;
};
vector<Node> tree[MAXN];
int dp[MAXN][];
int N; void init()
{
memset(dp,,sizeof(dp));
for(int i=;i<=N;i++)
tree[i].clear();
} void dfs1(int u,int fa)
{
int FirstMax=,SecondMax=;
for(int i=;i<tree[u].size();i++){
int v=tree[u][i].to;
int c=tree[u][i].cost;
if(v==fa) continue;
dfs1(v,u);
if(dp[v][]+c>FirstMax){
SecondMax=FirstMax;
FirstMax=dp[v][]+c;
}else if(dp[v][]+c>SecondMax)
SecondMax=dp[v][]+c;
}
dp[u][]=FirstMax;
dp[u][]=SecondMax;
} void dfs2(int u,int fa)
{
int t;
for(int i=;i<tree[u].size();i++){
int v=tree[u][i].to;
int c=tree[u][i].cost;
if(v==fa) continue;
if(dp[u][]==dp[v][]+c)
t=dp[u][];
else t=dp[u][];
dp[v][]=max(dp[u][],t)+c;
dfs2(v,u);
}
} int main()
{
while(scanf("%d",&N)==)
{
init();
int a,b;
Node n1;
for(int i=;i<=N;i++){
scanf("%d%d",&a,&b);
n1.to=a,n1.cost=b;
tree[i].push_back(n1);
n1.to=i;
tree[a].push_back(n1);
}
dfs1(,);
dfs2(,);
for(int i=;i<=N;i++)
printf("%d\n",max(dp[i][],dp[i][]));
}
return ;
}

最新文章

  1. redis的一些操作
  2. ASP.NET WebAPi之断点续传下载(上)
  3. EL表达式查询出来的数据,下载成excel表格,很实用的
  4. git学习笔记02-创建一个仓库提交一个文件-原来就是这么简单
  5. windows 下使用 MinGW + msys 编译 ffmpeg
  6. codeforces 691D Swaps in Permutation DFS
  7. keystone系列二:keystone源码分析
  8. 像web一样使用python
  9. ADF 项目创建流程
  10. HDU1024 Max Sum Plus Plus(DP)
  11. 用js写倒计时,向列表添加数据-------2017-03-21
  12. 201621123057 《Java程序设计》第7周学习总结
  13. 【Swift 3.0】iOS 国际化切换语言
  14. hdu 2829 Lawrence(四边形不等式优化dp)
  15. 用Volume在主机和Docker容器文件传输
  16. Mysql 关键字的优先级 分组 多表联查
  17. python基础(14)-反射&amp;类的内置函数
  18. python之模块的导入
  19. 利用history.pushState()实现页面无刷新更新
  20. laravel 接口跨域

热门文章

  1. 字符界面总是显示 login incorrect
  2. vue/npm 错误提示&amp;解决
  3. didFailWithError: Error Domain=kCLErrorDomain Code=0 “The operation couldn’t be completed. (kCLError
  4. laravel 下载报错:Unable to guess the mime type as no guessers are available
  5. spring cloud深入学习(六)-----熔断监控Hystrix Dashboard和Turbine
  6. Java过滤器—Filter用法简介
  7. 通信网络 ccf
  8. Java问题解读系列之基础相关---抽象类和接口
  9. 猜数字游戏_Python
  10. js创建svg元素的方法