HDU 2196 求树上所有点能到达的最远距离
其实我不是想做这道题的...只是今天考试考了一道类似的题...然后我挂了...
但是乱搞一下还是有80分....可惜没想到正解啊!
所以今天的考试题是:
巡访 (path.pas/c/cpp)
Chanxer终于当上了“中华农民联盟”的盟主,他举目四望,决定四处走走,巡视自己的农土。
“中华农民联盟”的成员有个村庄,在“村村通”计划中,村庄们被条道路联通了起来,Chanxer计划从某个村庄出发,访问所有的村庄。
可是Chanxer出行有一个特殊的要求,那就是必须以农车代步,现在我们知道哪些村庄配备有农车,也就是说,只有配备有农车的村庄才能够被作为出发点。
Chanxer有点懒,他想知道访问全部的村庄所要走的路程长度最小是多少。
树的节点数 n<=10^5
题目大意:已知一棵树,求一条满足一个端点为给定的端点的最长链。
其实就是求出每个点能到达的最远距离 [这就是我们的标题所给题目要求的]。
所以应该怎么做呢?
方法一:
经过证明,从树上任意一个点出发到达的最远的点一定是这棵树的直径的一个端点。
反过来,从直径的端点出发到达每个点的距离也一定是最远距离... [我怎么就没想到...囧]
所以先找到两个端点[先从随意一个点出发,然后这个点一定是一个端点,端点的最远点就是另一个端点],然后再跑一遍dfs就可以了[ 因为找第二个端点的时候已经跑过一遍了 ]...
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<queue>
#include<algorithm> using namespace std; inline int in(){
int x=;char ch=getchar();
while(ch>'' || ch<'') ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return x;
} const int maxn=;
const int INF=0x3f3f3f3f; struct Node{
int data,next,weight;
}node[maxn<<]; #define now node[point].data
#define then node[point].next
#define www node[point].weight int n,cnt;
long long M_dis,M_sit=,M_dis1;
int star[maxn];
int head[maxn];
bool vis[maxn];
long long ans,Sum;
long long f[maxn]; inline void add(int u,int v,int w){
node[cnt].data=v;node[cnt].next=head[u];node[cnt].weight=w;head[u]=cnt++;
node[cnt].data=u;node[cnt].next=head[v];node[cnt].weight=w;head[v]=cnt++;
} int dfs(int x,long long sum){
vis[x]=true;
if(sum>M_dis)
M_dis=sum,M_sit=x;
for(int point=head[x];point!=-;point=then)
if(!vis[now])
dfs(now,sum+www);
vis[x]=false;
} int dfs2(int x,long long sum){
vis[x]=true;f[x]=max(f[x],sum);
if(sum>M_dis)
M_dis=sum,M_sit=x;
for(int point=head[x];point!=-;point=then)
if(!vis[now])
dfs2(now,sum+www);
vis[x]=false;
} int main(){
freopen("path.in","r",stdin);
freopen("path.out","w",stdout); int u,v,w,cot=; n=in();
for(int i=;i<=n;i++) head[i]=-;
for(int i=;i<n;i++){
u=in(),v=in(),w=in(),add(u,v,w);
Sum+=w<<;
}
for(int i=;i<=n;i++) star[i]=in(),cot+=star[i]; dfs(,);
int t=M_sit;
dfs2(t,);
dfs2(M_sit,); for(int i=;i<=n;i++)
if(star[i])
ans=max(ans,f[i]); ans=Sum-ans; printf("%lld",ans); return ;
}
方法二:

详情可以见代码
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; inline int in(){
int x=;char ch=getchar();
while(ch>'' || ch<'') ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return x;
} const int maxn=; struct Node{
int data,next,weight;
}node[maxn<<]; #define now node[point].data
#define then node[point].next
#define www node[point].weight int n,cnt,ans,Sum;
int head[maxn];
int Max[maxn],Maxv[maxn];
int Smax[maxn],Smaxv[maxn]; inline void add(int u,int v,int w){
node[cnt].data=v;node[cnt].next=head[u];node[cnt].weight=w;head[u]=cnt++;
node[cnt].data=u;node[cnt].next=head[v];node[cnt].weight=w;head[v]=cnt++;
} void dfs(int x,int p){
for(int point=head[x];point!=-;point=then){
if(now==p) continue;
dfs(now,x);
if(Smax[x]<Max[now]+www){
Smax[x]=Max[now]+www,Smaxv[x]=now;
if(Smax[x]>Max[x]){
swap(Smax[x],Max[x]);
swap(Smaxv[x],Maxv[x]);
}
}
}
} void dfs2(int x,int p){
for(int point=head[x];point!=-;point=then){
if(now==p) continue;
if(now==Maxv[x]){
if(Smax[now]<Smax[x]+www){
Smax[now]=Smax[x]+www;Smaxv[now]=x;
if(Smax[now]>Max[now]){
swap(Smax[now],Max[now]);
swap(Smaxv[now],Maxv[now]);
}
}
}
else{
if(Smax[now]<Max[x]+www){
Smax[now]=Max[x]+www;Smaxv[now]=x;
if(Smax[now]>Max[now]){
swap(Smax[now],Max[now]);
swap(Smaxv[now],Maxv[now]);
}
}
}
dfs2(now,x);
}
} int main(){
freopen("path.in","r",stdin);
freopen("path.out","w",stdout); int u,v,w; n=in();
for(int i=;i<=n;i++) head[i]=-;
for(int i=;i<n;i++)
u=in(),v=in(),w=in(),add(u,v,w),Sum+=(w<<); dfs(,-);
dfs2(,-); for(int i=;i<=n;i++)
if(u=in()) ans=max(ans,Max[i]); printf("%d",Sum-ans); return ;
}
另附标题的AC通道:
http://acm.hdu.edu.cn/showproblem.php?pid=2196
HDU 2196 求树上所有点能到达的最远距离的更多相关文章
- HDU 2196 Computer (树上最长路)【树形DP】
<题目链接> 题目大意: 输出树上每个点到其它点的最大距离. 解题分析: 下面的做法是将树看成有向图的做法,计算最长路需要考虑几种情况. dp[i][0] : 表示以i为根的子树中的结点与 ...
- HDU 2196 Computer( 树上节点的最远距离 )
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- hdu 2196(方法1:经典树形DP+方法2:树的直径)
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- 求树上任意一点所能到达的最远距离 - 树上dp
A school bought the first computer some time ago(so this computer's id is 1). During the recent year ...
- HDU 2196.Computer 树形dp 树的直径
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- HDU 2196树形DP(2个方向)
HDU 2196 [题目链接]HDU 2196 [题目类型]树形DP(2个方向) &题意: 题意是求树中每个点到所有叶子节点的距离的最大值是多少. &题解: 2次dfs,先把子树的最大 ...
- hdu 2196【树形dp】
http://acm.hdu.edu.cn/showproblem.php?pid=2196 题意:找出树中每个节点到其它点的最远距离. 题解: 首先这是一棵树,对于节点v来说,它到达其它点的最远距离 ...
- HDU 2196 树形DP Computer
题目链接: HDU 2196 Computer 分析: 先从任意一点开始, 求出它到其它点的最大距离, 然后以该点为中心更新它的邻点, 再用被更新的点去更新邻点......依此递推 ! 代码: ...
- 【HDU 2196】 Computer(树的直径)
[HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...
随机推荐
- 学习实践:使用模式,原则实现一个C++自动化测试程序
个人编程中比较喜欢重构,重构能够提高自己的代码质量,使代码阅读起来也更清晰.但是重构有一个问题,就是如何保证重构后带代码实现的功能与重构前的一致,如果每次重构完成后,对此不闻不问,则会有极大的风险,如 ...
- PHP常用函数和常见疑难问题解答
PHP常用库函数介绍 一.PHP字符串操作常用函数 1.确定字符串长度 int strlen(string str) 2.比较两个字符串 a. strcmp函数对两个字符串进行二进制安全的比较,并区 ...
- FaceBook微光闪烁---第三方开源--shimmer-android
Android上的微光闪烁shimmer效果,实现的手段不少,其中比较好的是facebook做的开源库:shimmer-android,其在github上的项目主页是:https://github.c ...
- linux安装至少有哪两个分区,各自作用是什么?
1.至少有/代表根分区,/swap代表的意思是交换分区. 2.swap相当于缓存的作用:
- 给Activity设置背景颜色
为了使得错误提示更加显眼,再用Toast+振动效果之外考虑变换整个activity的背景颜色. 尝试一: activity并没像winform一样直接给个属性来设置,就想获取整个activity的la ...
- 【微网站开发】之微信内置浏览器API使用
最近在写微网站,发现了微信内置浏览器的很多不称心的地方: 1.安卓版的微信内浏览器底部总是出现一个刷新.前进.后退的底部栏,宽度很大,导致屏幕显示尺寸被压缩 2.分享当前网站至朋友圈时,分享的图片一般 ...
- 在newegg工作的这两个月
6月11号,接到录用通知后的第二天,来到了Newegg . 作为开发,在本职工作上 1.入职Quick Start: 两周多的入职快速指引,以了解业务,架构为目的. 因为之前一直有用思维导图的习惯,所 ...
- 说说oracle中的面向对象与面向集合
这一篇算是对近期自己学习的一个心得总结 一.oracle的面向对象 SQL是面向集合的这个大家都知道,但是不可否认现在的oracle中有很多地方都体现着面向对象的思维.(这也算是各大语言殊途同归的一个 ...
- hdu 1305 Immediate Decodability
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1305 字典树裸题,如下: #include<algorithm> #include< ...
- 修改linux端口范围 ip_local_port_range
tags: ip_local_port_range 端口范围 sysctl Linux中有限定端口的使用范围,如果我要为我的程序预留某些端口,那么我需要控制这个端口范围, 本文主要描述如何去修改端口范 ...