loj 1257 (求树上每一个点到树上另一个点的最长距离)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1257
思路:首先需要用到一个知识点就是树上任一点到树上最长直径的某一个端点的距离最远,因此我们可以用dp[u]表示从u点出发到的最远距离,然后从任意一点出发,一遍dfs求出树上最长直径的某一个端点,然后从这个端点出发,再次dfs求出另一个端点,最后在从求出的端点出发进行dfs更新.每次做dfs时都更新一下dp.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 const int MAXN = (30000 + 30); 9 struct Edge { 10 int v, w, next; 11 }edge[MAXN << 1]; 12 int n, ans, NE, End, maxlen; 13 int head[MAXN]; 14 15 void Insert(int u, int v, int w) 16 { 17 edge[NE].v = v; 18 edge[NE].w = w; 19 edge[NE].next = head[u]; 20 head[u] = NE++; 21 } 22 23 int dp[MAXN]; 24 void dfs(int u, int father, int len) 25 { 26 if (len > maxlen) { 27 maxlen = len; 28 End = u; 29 } 30 for (int i = head[u]; i != -1; i = edge[i].next) { 31 int v = edge[i].v; 32 int w = edge[i].w; 33 if (v == father) continue; 34 dfs(v, u, len + w); 35 dp[v] = max(dp[v], len + w); 36 } 37 } 38 39 int main() 40 { 41 int _case, t = 1; 42 scanf("%d", &_case); 43 while (_case--) { 44 scanf("%d", &n); 45 NE = 0; 46 memset(head, -1, sizeof(head)); 47 for (int i = 1; i < n; i++) { 48 int u, v, w; 49 scanf("%d %d %d", &u, &v, &w); 50 Insert(u, v, w); 51 Insert(v, u, w); 52 } 53 maxlen = 0; 54 memset(dp, 0, sizeof(dp)); 55 dfs(1, -1, 0); 56 dfs(End, -1, 0); 57 dfs(End, -1, 0); 58 printf("Case %d:\n", t++); 59 for (int i = 0; i < n; i++) { 60 printf("%d\n", dp[i]); 61 } 62 } 63 return 0; 64 }