[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 ...
随机推荐
- 再看python多线程------threading模块
现在把关于多线程的能想到的需要注意的点记录一下: 关于threading模块: 1.关于 传参问题 如果调用的子线程函数需要传参,要在参数后面加一个“,”否则会抛参数异常的错误. 如下: for i ...
- Unix环境高级编程---信号
参考博客:http://blog.csdn.net/alex_my/article/details/39494129 1. 信号概念 何为信号? 信号是一种软中断,可以由以下情形触发: -1: 用户按 ...
- hdu 4927 java程序
/*对于本题题意非常easy 关键在于求杨辉三角时的二项式是没实用到优化,导致超时. 对于第n行的二项式的第i个可有第i-1个乘于一个数处于一个数得到,要用到大数.java比較方便. 假如n=6,i= ...
- php微信支付测试开发(流程已通)
必要条件: appid //公众号后台开发者中心获得(和邮件内的一样) mchid//邮件内获得 key//商户后台自己设置 appsecret //公众号开发者中心获得 两个证书文件,邮件内 ...
- (*)(转)要快速学习SSM框架,你需要一套学习曲线平滑的教程
作者:meepo链接:https://www.zhihu.com/question/57719761/answer/156952139来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...
- 【Windows】修改远程桌面端口号
echo off echo 修改远程连接端口 reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Se ...
- h大数据
安全认证 hw HBase安全认证(创建HBaseHolder时认证) String userPrincipal = FeatureContext.INSTANCE.getOrElse(Constan ...
- java.util.ResourceBundle国际化用法详解
java.util.ResourceBundle国际化用法详解 初识国际化和ResourceBundle 这个类主要用来解决国际化和本地化问题.国际化和本地化可不是两个概念,两者都是一起出现的.可以说 ...
- BMP文件解析【转】
本文转载自:http://blog.csdn.net/Blues1021/article/details/44954817 BMP文件通常是不压缩的,所以它们通常比同一幅图像的压缩图像文件格式要大很多 ...
- oracle_sql的用法?
本机连接oracle 数据库?打开cmd ----> 不同的用户有不同的用户名密码 ----> sqlplus scott/tiger(安装oracle数据库预留的用户)---- 回车 - ...