树的中心

给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。

请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。

输入格式

第一行包含整数 n。

接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。

输出格式

输出一个整数,表示所求点到树中其他结点的最远距离。

数据范围

1≤n≤10000,
1≤ai,bi≤n,
−10^5≤ci≤10^5

输入样例:

  1.  
    5
  2.  
    2 1 1
  3.  
    3 2 1
  4.  
    4 3 1
  5.  
    5 1 1

输出样例:

2

分析:

树的中心:树中找到一个点,该点到树中其他结点的最远距离最近。

为求得当前点到树中其他节点的最远距离,有两种遍历方式:

 

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 const int N = 10000+10;
 5 int head[N],nexts[N*2],ver[N*2],edge[N*2];
 6 int tot,INF=0x3f3f3f3f;
 7 int down1[N],down2[N],up[N],p[N];
 8 void add(int x,int y,int z){
 9     ver[++tot]=y,edge[tot]=z;
10     nexts[tot]=head[x],head[x]=tot;
11 }
12 //子节点更新父节点
13 int dfs_down(int x,int father){
14     down1[x]=down2[x]=-INF;
15     for(int i=head[x];i;i=nexts[i]){
16         int y=ver[i],z=edge[i];
17         if(y==father) continue;
18         int d=dfs_down(y,x)+z;
19         if(d>down1[x]){
20             down2[x]=down1[x],down1[x]=d;
21             p[x]=y;
22         }
23         else if(d>down2[x]) down2[x]=d;
24     }
25     if(down1[x]==-INF&&down2[x]==-INF) down1[x]=down2[x]=0;
26     return down1[x];
27 }
28 //父节点更新子节点
29 void dfs_up(int x,int father){
30     for(int i=head[x];i;i=nexts[i]){
31         int y=ver[i],z=edge[i];
32         if(y==father) continue;
33         if(p[x]==y) up[y]=max(up[x],down2[x])+z;
34         else up[y]=max(up[x],down1[x])+z;
35         dfs_up(y,x);
36     }
37 }
38 int main(){
39     int n;
40     scanf("%d",&n);
41     for(int i=0;i<n;i++){
42         int x,y,z;
43         scanf("%d%d%d",&x,&y,&z);
44         add(x,y,z);
45         add(y,x,z);
46     }
47     dfs_down(1,0);
48     dfs_up(1,0);
49     int res=INF;
50     for(int i=1;i<=n;i++){
51         res=min(res,max(down1[i],up[i]));
52     }
53     printf("%d",res);
54     return 0;
55 }

 

posted @ 2020-10-16 21:17  古比  阅读(226)  评论(0编辑  收藏  举报