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# dataset 索引0没有值
datatable绑定到dataGrieView,在刷新datatable的数据时,常会bug:索引0没有值或索引(int)x没有值 昨天弄了一个下午,发现bug原因: dataGridView中有数 ...
- [Redis] RDB & AOF
http://my.oschina.net/davehe/blog/174662 rdb - 存在dump.rdb 的二进制文件中 dump 整个db, 数据多的时候,不合适频繁保存,保存的时间间隔应 ...
- 自制tab页
没事自己弄着玩,写了个tab页.不要当真.想看就看看.希望相互学习. 效果预览:html源码: <!DOCTYPE html> <html lang="en"&g ...
- BT9034: 仅 IE 和 Opera 支持 HTMLFrameElement 和 HTMLIFrameElement 的 document 属性
标准参考 根据 DOM-2 中的描述,HTMLFrameElement 和 HTMLIFrameElement 都没有 'document' 属性. 关于 HTMLFrameElement 对象的详细 ...
- Java transient volatile关键字(转)
Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...
- PHP 简单实现MySQL数据搜索、添加数据功能 以设备管理为例
测试截图: 数据库bzec ,表shebeidangan 列sb_name,sb_numandtype,sb_home,sb_usedate,sb_address,sb_updatetime,sb_r ...
- STM32F0xx_TIM输入捕获(计算频率)配置详细过程
前言 关于STM32的定时器,可谓是功能强大,估计没有多少人研究完STM32定时器的所有功能(包括我也没有),只是使用常用的一些功能,后续我会推出关于STM32定时器的更多功能. STM32芯片多数为 ...
- 【Cocoa】 Initializing View Instances Created in Interface Builder
Initializing View Instances Created in Interface Builder View instances that are created in Interfac ...
- Linq操作
Linq使用Group By 1 1.简单形式: var q = from p in db.Products group p by p.CategoryID into g select g; 语句描述 ...
- C实现辗转相除法求两个数的最大公约数
什么是辗转相除法? 辗转相除法(又名欧几里德算法),它主要用于求两个正整数的最大公约数.是已知的最古老的算法. 用辗转相除法求132和72的最大公约数的步骤: 132 / 72 = 1 ... 60 ...