[hdu2196]Computer树的直径
题意:求树中距离每个节点的最大距离。
解题关键:两次dfs,第一次从下向上dp求出每个节点子树中距离其的最大距离和不在经过最大距离上的子节点上的次大距离(后序遍历),第二次从上而下dp求出其从父节点过来的最大距离(先序遍历).

如果vi不是u最长距离经过的节点,$d[{v_i}][2] = dist[{v_i}][u] + \max (d[u][0],d[u][2])$;
如果vi是u最长距离经过的节点,$d[{v_i}][2] = dist[{v_i}][u] + \max (d[u][1],d[u][2]);$
最终答案即是从下而来和从上而来的距离的最大值。
取最大值和次大值时的>=和>是无所谓的,都可以过
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
int head[maxn],tot,d[maxn][],longest[maxn];
struct edge{
int to;
int nxt;
int w;
}e[maxn<<];
void add_edge(int u,int v,int w){
e[tot].to=v;
e[tot].w=w;
e[tot].nxt=head[u];
head[u]=tot++;
} int dfs1(int u,int fa){//返回子树最大距离
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
int tmp=dfs1(v,u);
if(d[u][]<tmp+e[i].w){
longest[u]=v;
d[u][]=d[u][];
d[u][]=tmp+e[i].w;
}else if(d[u][]<tmp+e[i].w){//求次大距离必须加else if
d[u][]=tmp+e[i].w;
}
}
return d[u][];
} void dfs2(int u,int fa){
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
if(v==longest[u]) d[v][]=max(d[u][],d[u][])+e[i].w;
else d[v][]=max(d[u][],d[u][])+e[i].w;
dfs2(v,u);
}
} int main(){
int n;
ios::sync_with_stdio();
cin.tie();
cout.tie();
while(cin>>n){
tot=;
memset(d,,sizeof d);
memset(head,-,sizeof head);
memset(longest,,sizeof longest);
int a,b;
for(int i=;i<=n;i++){
cin>>a>>b;
add_edge(i,a,b);
add_edge(a,i,b);
}
dfs1(,-);
dfs2(,-);
for(int i=;i<=n;i++){
cout<<max(d[i][],d[i][])<<"\n";
}
}
return ;
}
最优写法:
不需要记录longest,只要d[v][0]+e[i].w==d[u][0],此时即可取次大距离。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
int head[maxn],tot,d[maxn][];
struct edge{
int to;
int nxt;
int w;
}e[maxn<<];
void add_edge(int u,int v,int w){
e[tot].to=v;
e[tot].w=w;
e[tot].nxt=head[u];
head[u]=tot++;
} void dfs1(int u,int fa){//返回子树最大距离
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
dfs1(v,u);
int tmp=d[v][]+e[i].w;
if(d[u][]<=tmp){
d[u][]=d[u][];
d[u][]=tmp;
}else if(d[u][]<tmp){//求次大距离必须加else if
d[u][]=tmp;
}
}
} void dfs2(int u,int fa){
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
if(d[u][]==d[v][]+e[i].w) d[v][]=max(d[u][],d[u][])+e[i].w;
else d[v][]=max(d[u][],d[u][])+e[i].w;
dfs2(v,u);
}
} int main(){
int n;
ios::sync_with_stdio();
cin.tie();
cout.tie();
while(cin>>n){
tot=;
memset(d,,sizeof d);
memset(head,-,sizeof head);
int a,b;
for(int i=;i<=n;i++){
cin>>a>>b;
add_edge(i,a,b);
add_edge(a,i,b);
}
dfs1(,-);
dfs2(,-);
for(int i=;i<=n;i++){
cout<<max(d[i][],d[i][])<<"\n";
}
}
return ;
}
[hdu2196]Computer树的直径的更多相关文章
- 【HDU 2196】 Computer(树的直径)
[HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...
- hdu 2196 Computer 树的直径
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...
- HDOJ 2196 Computer 树的直径
由树的直径定义可得,树上随意一点到树的直径上的两个端点之中的一个的距离是最长的... 三遍BFS求树的直径并预处理距离....... Computer Time Limit: 1000/1000 MS ...
- codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径
题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” ...
- codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点
J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Des ...
- HDU 2196.Computer 树形dp 树的直径
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- [J]computer network tarjan边双联通分量+树的直径
https://odzkskevi.qnssl.com/b660f16d70db1969261cd8b11235ec99?v=1537580031 [2012-2013 ACM Central Reg ...
- computer(树形dp || 树的直径)
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- hdu2196 树的直径 + bfs
//Accepted 740 KB 15 ms //树的直径 //距离一个顶点最远的点一定是树的直径的一个端点 #include <cstdio> #include <cstring ...
随机推荐
- wpf自定义colorpicker
自定义colorpicker <ObjectDataProvider MethodName="GetType" ObjectType="{x:Type system ...
- 下面哪个进制能表述 13*16=244是正确的?)[中国台湾某计算机硬件公司V2010年5月面试题]
A.5B.7C.9D.11解析:13如果是一个十进制的话,它可以用13=1*101+3*100来表示.现在我们不知道13是几进制,那我们姑且称其X进制.X进制下的13转化为十进制可以用13=1*X1+ ...
- c++动态绑定的技术实现
1 什么是动态绑定 有一个基类,两个派生类,基类有一个virtual函数,两个派生类都覆盖了这个虚函数.现在有一个基类的指针或者引用,当该基类指针或者引用指向不同的派生类对象时,调用该虚函数,那么最终 ...
- Magnetic Fingerprinting Approach to Indoor Localization
Magnetic Fingerprinting Approach to Indoor Localization
- 我的Java开发学习之旅------>Java经典排序算法之快速排序
一.算法思想 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod).(1) 分治法的 ...
- JavaScript及jQuery学习小结
最近几天学习了很多关于JavaScript和jQuery的文章,稍作梳理后,总结如下. 1.jQuery入门系列 环境搭建 只需引用一个jQuery库文件,即可完成jQuery的环境搭建. 选择器 j ...
- selector + drawable 多状态图形
select_drawble.xml<?xml version="1.0" encoding="utf-8"?> <selector xmln ...
- 自定义编辑框VC,可加载更改字体,添加背景图片,显示输入提示信息
搞了一天终于弄了个完整的编辑框控件出来了, 哎,,,搞界面开发还是有点复杂的. #pragma once #include "AdvEdit.h" // CBkgEditBox c ...
- smokeping 出现的问题
Global symbol "%Config" requires explicit package name at /usr/lib64/perl5/lib.pm line 10. ...
- matlab的数组
1.定义:同一类型的元素的集合. 2.生成:用[]创建,元素之间用逗号或者空格隔开. 第一例: >>a=[1,2,3,4] a = 1 2 3 4 注意,取矩阵的某几列,是这样a(:,2: ...