【模板】tyvjP1520 树的直径 [2017年5月计划 清北学堂51精英班Day3]

P1520 树的直径
时间: 1000ms / 空间: 131072KiB / Java类名: Main

描述

树的直径,即这棵树中距离最远的两个结点的距离。每两个相邻的结点的距离为1,即父亲结点与儿子结点或儿子结点与父子结点之间的距离为1.有趣的是,从树 的任意一个结点a出发,走到距离最远的结点b,再从结点b出发,能够走的最远距离,就是树的直径。树中相邻两个结点的距离为1。你的任务是:给定一棵树, 求这棵树中距离最远的两个结点的距离。

输入格式

输入共n行
第一行是一个正整数n,表示这棵树的结点数
接下来的n-1行,每行三个正整数a,b,w。表示结点a和结点b之间有一条边,长度为w
数据保证一定是一棵树,不必判错。

输出格式

输出共一行
第一行仅一个数,表示这棵树的最远距离

测试样例1

输入

4
1 2 10
1 3 12
1 4 15

输出

27

备注

10%的数据满足1<=n<=5
40%的数据满足1<=n<=100
100%的数据满足1<=n<=10000 1<=a,b<=n 1<=w<=10000Tgotmacp
 
 
两种方法。
 
第一种钦定一个根节点,以香港记者的速度跑一边BFS并找到最长链。
然后钦定最长链的终点为根,再以香港记者的速度跑一边BFS,找到的最长链就是直径。
 
第二种钦定一个根节点,dfs或dfs,从下往上,记dp1[i]为节点i下面子树的最长链长,dp2[i]为节点i下面子树的次长链长,答案是两个加和。
 
求-1s
 
方法1:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #define max(a,b) ((a) > (b) ? (a) : (b))
 7 #define min(a,b) ((a) > (b) ? (b) : (a))
 8 #define lowbit(a) ((a) & (-(a)))
 9 
10 int read()
11 {
12     int x = 0;char ch = getchar();char c = ch;
13     while(ch > '9' || ch < '0')c = ch, ch = getchar();
14     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
15     if(c == '-')return -x;
16     return x;
17 }
18 
19 const int INF = 0x3f3f3f3f;
20 const int MAXN = 10000 + 10;
21 const int MAXE = MAXN * 2;
22 
23 int head[MAXN];
24 int cnt;
25 int n;
26 int tmp1,tmp2,tmp3;
27 struct Edge
28 {
29     int u,v,w,next;
30 }edge[MAXE];
31 inline void insert(int a,int b,int c)
32 {
33     edge[++cnt] = Edge{a,b,c,head[a]};
34     head[a] = cnt;
35 }
36 inline void init()
37 {
38     n = read();
39     for(int i = 1;i < n;i ++)
40     {
41         tmp1 = read();tmp2 = read();tmp3 = read();
42         insert(tmp1, tmp2, tmp3);
43         insert(tmp2, tmp1, tmp3);
44     } 
45 }
46 
47 int queue[MAXN];
48 int ans;
49 bool b[MAXN];
50 int lenth[MAXN];//lenth[i]表示节点i到根节点的长度 
51 int bfs(int root)
52 {
53     memset(queue, 0, sizeof(queue));
54     memset(b, 0, sizeof(b));
55     int head = 1,tail = 1;
56     int a = 1;
57     queue[tail] = root;
58     lenth[root] = 0;
59     b[root] = true;
60     
61     int mnode = root,m = 0;
62     do
63     {
64         int x = queue[head];
65         head ++;
66         for(int pos = ::head[x];pos;pos = edge[pos].next)
67         {
68             int tmp = edge[pos].v;
69             if(!b[tmp])
70             {
71                 b[tmp] = true;
72                 queue[++tail] = tmp;
73                 lenth[tmp] = lenth[x] + edge[pos].w;
74                 if(lenth[tmp] > m)m = lenth[tmp],mnode = tmp;
75                 a ++;
76             }
77         }
78     }while(a < n); 
79     ans = max(ans, m);
80     return mnode;
81 }
82 inline void work()
83 {
84     bfs(bfs(1));
85 }
86 inline void shuchu()
87 {
88     printf("%d", ans);
89 }
90 int main()
91 {
92     init();
93     work();
94     shuchu();
95     return 0;
96 }
 

方法2:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <algorithm>
  6 #define max(a,b) ((a) > (b) ? (a) : (b))
  7 #define min(a,b) ((a) > (b) ? (b) : (a))
  8 #define lowbit(a) ((a) & (-(a)))
  9 
 10 int read()
 11 {
 12     int x = 0;char ch = getchar();char c = ch;
 13     while(ch > '9' || ch < '0')c = ch, ch = getchar();
 14     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
 15     if(c == '-')return -x;
 16     return x;
 17 }
 18 
 19 const int INF = 0x3f3f3f3f;
 20 const int MAXN = 10000 + 10;
 21 const int MAXE = MAXN * 2;
 22 
 23 int head[MAXN];
 24 int cnt;
 25 int n;
 26 int tmp1,tmp2,tmp3;
 27 struct Edge
 28 {
 29     int u,v,w,next;
 30 }edge[MAXE];
 31 inline void insert(int a,int b,int c)
 32 {
 33     edge[++cnt] = Edge{a,b,c,head[a]};
 34     head[a] = cnt;
 35 }
 36 inline void init()
 37 {
 38     n = read();
 39     for(int i = 1;i < n;i ++)
 40     {
 41         tmp1 = read();tmp2 = read();tmp3 = read();
 42         insert(tmp1, tmp2, tmp3);
 43         insert(tmp2, tmp1, tmp3);
 44     } 
 45 }
 46 
 47 int queue[MAXN];
 48 int ans;
 49 bool b[MAXN];
 50 int dp1[MAXN];//最长路
 51 int dp2[MAXN];//次长路 
 52 int lenth[MAXN];//lenth[i]表示节点i到根节点的长度 
 53 void bfs(int root)
 54 {
 55     int head = 1,tail = 1;
 56     int a = 1;
 57     queue[tail] = root;
 58     lenth[root] = 0;
 59     b[root] = true;
 60     
 61     int mnode = root,m = 0;
 62     do
 63     {
 64         int x = queue[head];
 65         head ++;
 66         for(int pos = ::head[x];pos;pos = edge[pos].next)
 67         {
 68             int tmp = edge[pos].v;
 69             if(!b[tmp])
 70             {
 71                 b[tmp] = true;
 72                 queue[++tail] = tmp;
 73                 a ++;
 74             }
 75         }
 76     }while(a < n);
 77     for(int i = tail;i >= 1;i --)
 78     {
 79         int x = queue[i];
 80         if(!::head[i])
 81         {
 82             b[i] = false;
 83         }
 84         else
 85         {
 86             int m1 = 0,m2 = 0;
 87             for(int pos = ::head[x];pos;pos = edge[pos].next)
 88             {
 89                 int tmp = edge[pos].v;
 90                 if(!b[tmp])
 91                 {
 92                     if(m1 < dp1[tmp] + edge[pos].w)
 93                     {
 94                         m2 = m1;
 95                         m1 = dp1[tmp] + edge[pos].w;
 96                     } 
 97                     else if(m2 < dp1[tmp] + edge[pos].w)
 98                     {
 99                         m2 = dp1[tmp] + edge[pos].w;
100                     }
101                 }
102             }
103             dp1[x] = m1;dp2[x] = m2;
104         }
105         b[x] = false;
106         ans = max(ans, dp1[x] + dp2[x]);
107     }
108 }
109 inline void work()
110 {
111     bfs(1);
112 }
113 inline void shuchu()
114 {
115     printf("%d", ans);
116 }
117 int main()
118 {
119     init();
120     work();
121     shuchu();
122     return 0;
123 }
 
原文地址:https://www.cnblogs.com/huibixiaoxing/p/6914312.html