首页 > 代码库 > 树上某点距离最远的结点

树上某点距离最远的结点

题目链接

题目需要得到树上每个结点出发可到达的最远的结点,顺便求出树的直径。

这里顺便总结一下求解的两种方法。

第一种思路:三种dfs(bfs)

  第一遍dfs(bfs)从任意结点出发,找到距离该结点最远的结点u(直径的端点之一)。

  第二遍dfs(bfs)从u出发,求出其他点到u的距离,最长的即为v(直径的另一个端点)。  第三遍dfs(bfs)从v出发,求出其他点到v的距离。  可以知道,对于任意结点x,其在树上可到达的最远的距离为max{dist[x][u], dist[x][v]}.  故其最大值即为树的直径。这样,就可以满足题目需求了。第二种思路:树dp(两次不同的dfs)  首先,该种方法需要记录每个结点到以其为根的子树中所以结点距离的最大值f[x]和次大值g[x].  这个可以由第一次dfs得到(以任意结点为根)。  第二次dfs就是一个树dp, 需要得到每个结点可以到达的最远距离far[x].  这里,树的直径即为max{fax[x]}. 当然,也可以根据树的直径diam = max{f[x] + g[x]}得到。最后附上代码:第一种:
 1 /************************************************************************* 2     > File Name: 19C.cpp 3     > Author: Stomach_ache 4     > Mail: sudaweitong@gmail.com 5     > Created Time: 2014年12月01日 星期一 18时31分41秒 6     > Propose: 树的直径以及树上某点能到达的最远结点 7  ************************************************************************/ 8 #include <queue> 9 #include <cmath>10 #include <string>11 #include <vector>12 #include <cstdio>13 #include <fstream>14 #include <cstring>15 #include <iostream>16 #include <algorithm>17 using namespace std;18 /*Let‘s fight!!!*/19 20 const int MAX_N = 100050;21 const int INF = 0x3f3f3f3f;22 typedef long long LL;23 #define rep(i, n) for (int i = (0); i < (n); i++)24 vector<int> G[MAX_N];25 int distA[MAX_N], distB[MAX_N];26 bool vis[MAX_N];27 28 void bfs(int s, int *dist) {29     fill(dist, dist + MAX_N, -INF);30     queue<int> Q;31     Q.push(s);32     dist[s] = 0;33     while (!Q.empty()) {34         int now = Q.front(); Q.pop();35         vis[now] = true;36         int sz = G[now].size();37         for (int i = 0; i < sz; i++) {38             int nxt = G[now][i];39             if (!vis[nxt]) {40                 Q.push(nxt);41                 dist[nxt] = dist[now] + 1;42             } 43         }44     }45 }46 47 int main(void) {48     int N, M;49     scanf("%d %d", &N, &M);50     rep (i, N-1) {51         int u, v;52         scanf("%d %d", &u, &v);53         G[u].push_back(v);54         G[v].push_back(u);55     }56 57     bfs(1, distA);58     int u = 1;59     for (int i = 2; i <= N; i++) if (distA[i] > distA[u]) u = i;60     61     memset(vis, false, sizeof(vis));62     bfs(u, distA);63     int v = 1;64     for (int i = 2; i <= N; i++) if (distA[i] > distA[v]) v = i;65 66     memset(vis, false, sizeof(vis));67     bfs(v, distB);68     LL diam = distA[v];69     while (M--) {70         int v, k;71         scanf("%d %d", &v, &k);72         printf("%lld\n", diam * (k - 1) + max(distA[v], distB[v]));73     }74     return 0;75 }

第二种:

 

 1 /************************************************************************* 2     > File Name: 19C_dp.cpp 3     > Author: Stomach_ache 4     > Mail: sudaweitong@gmail.com 5     > Created Time: 2014年12月01日 星期一 19时02分44秒 6     > Propose:  7  ************************************************************************/ 8  9 #include <cmath>10 #include <string>11 #include <cstdio>12 #include <vector>13 #include <fstream>14 #include <cstring>15 #include <iostream>16 #include <algorithm>17 using namespace std;18 /*Let‘s fight!!!*/19 20 const int MAX_N = 100050;21 const int INF = 0x3f3f3f3f;22 typedef long long LL;23 vector<int> G[MAX_N];24 int dp[2][MAX_N], far[MAX_N];25 26 void dfs(int u, int fa) {27     int sz = G[u].size();28     for (int i = 0; i < sz; i++) {29         int v = G[u][i];30         if (v != fa) {31             dfs(v, u);32             if (dp[0][v] + 1 > dp[0][u]) {33                 dp[1][u] = dp[0][u];34                 dp[0][u] = dp[0][v] + 1;35             } else if(dp[0][v] + 1 > dp[1][u]) {36                 dp[1][u] = dp[0][v] + 1;37             }38         }39     }40 }41 42 void dfs2(int u, int fa, int up) {43     int sz = G[u].size();    44     far[u] = max(dp[0][u], up);45     for (int i = 0; i < sz; i++) {46         int v = G[u][i];47         if (v != fa) {48             if (dp[0][v] + 1 == dp[0][u]) dfs2(v, u, max(up, dp[1][u])+1);49             else dfs2(v, u, max(up, dp[0][u])+1);50         }51     }52 }53 54 int main(void) {55     int N, M;56     scanf("%d %d", &N, &M);57     for (int i = 0; i < N - 1; i++) {58         int u, v;59         scanf("%d %d", &u, &v);60         G[u].push_back(v);61         G[v].push_back(u);62     }63 64     dfs(1, -1);65     dfs2(1, -1, 0);66 67     LL diam = 0;68     //两者等价69     //for (int i = 1; i <= N; i++) if (dp[0][i] + dp[1][i] > diam) diam = dp[0][i] + dp[1][i];70     for (int i = 1; i <= N; i++) if (far[i] > diam) diam = far[i];71     while (M--) {72         int v, k; 73         scanf("%d %d", &v, &k);74         printf("%lld\n", diam * (k - 1) + far[v]);75     }76     return 0;77 }

树上某点距离最远的结点