其实我不是想做这道题的...只是今天考试考了一道类似的题...然后我挂了...

但是乱搞一下还是有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 求树上所有点能到达的最远距离的更多相关文章

  1. HDU 2196 Computer (树上最长路)【树形DP】

    <题目链接> 题目大意: 输出树上每个点到其它点的最大距离. 解题分析: 下面的做法是将树看成有向图的做法,计算最长路需要考虑几种情况. dp[i][0] : 表示以i为根的子树中的结点与 ...

  2. HDU 2196 Computer( 树上节点的最远距离 )

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. hdu 2196(方法1:经典树形DP+方法2:树的直径)

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  4. 求树上任意一点所能到达的最远距离 - 树上dp

    A school bought the first computer some time ago(so this computer's id is 1). During the recent year ...

  5. HDU 2196.Computer 树形dp 树的直径

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  6. HDU 2196树形DP(2个方向)

    HDU 2196 [题目链接]HDU 2196 [题目类型]树形DP(2个方向) &题意: 题意是求树中每个点到所有叶子节点的距离的最大值是多少. &题解: 2次dfs,先把子树的最大 ...

  7. hdu 2196【树形dp】

    http://acm.hdu.edu.cn/showproblem.php?pid=2196 题意:找出树中每个节点到其它点的最远距离. 题解: 首先这是一棵树,对于节点v来说,它到达其它点的最远距离 ...

  8. HDU 2196 树形DP Computer

    题目链接:  HDU 2196 Computer 分析:   先从任意一点开始, 求出它到其它点的最大距离, 然后以该点为中心更新它的邻点, 再用被更新的点去更新邻点......依此递推 ! 代码: ...

  9. 【HDU 2196】 Computer(树的直径)

    [HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...

随机推荐

  1. winfrom 导入Excel表到access数据库(来自小抽奖系统)

    网上有很多这种方法,本人只是针对自己的系统来实现的 //导入excel表 private void ImportTSMenu_Click(object sender, EventArgs e) { O ...

  2. DataGridView 控件用法(可能不是很全面,因为这是自己常常用到的一些小总结):

    一.DataGridView属性设置 1.我们单击选中行的时候,默认是选择一个单元格,不能选择一整行,我们只需设置DataGridView的属性SelectionMode为FullRowSelect ...

  3. scala学习笔记2

    一.算术和操作符重载 a + b 是如下方法的简写: a.+(b) 在scala中你可以使用任何符号来为方法命名.比如BigInt类就定义了一个/%的方法,该方法返回一个对偶,对偶的内容是除法操作得到 ...

  4. ElasticSearch部署

    安装jdk1.7 1.卸载Liunx自带的openjdk rpm -qa | grep jdk 查看当前的jdk版本 sudo yum -y remove java-1.7.0-openjdk-hea ...

  5. Sorl之.net操作

    http://www.cnblogs.com/zhangweizhong/category/771055.html 插入: SolrNet.Startup.Init<Movie>(&quo ...

  6. 新成员!Visual Studio Code --跨平台的开发工具(支持OSX, Linux 和 Windows)

    原文出处:新成员!Visual Studio Code --跨平台的开发工具(支持OSX, Linux 和 Windows) 这是我的文章备份  http://www.dotblogs.com.tw/ ...

  7. C# 代码重启windows服务

    ServiceController service = new ServiceController("EnergyRecordService"); protected void b ...

  8. WPF控件数据单项绑定

    建立一个姓名,年龄输入框,如图: XAML代码: <TextBox Name="txtName" Text="{Binding Name}" ToolTi ...

  9. Win8.1想要卸载openSUSE出现问题(2014.8.15已解决)

    用DiskGenius激活C盘后果然好用了!随便用EasyBCD恢复一下就好了 下面再说说安装openSUSE这半周多的问题: 1.如果是NVIDIA和Intel双显卡就不要安装NVIDIA的显卡驱动 ...

  10. Cron表达式说明

    CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表. CronT ...