• 树上某点距离最远的结点


    题目链接

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

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

    第一种思路:三种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
    ", 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
    ", diam * (k - 1) + far[v]);
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    时间序列深度学习:seq2seq 模型预测太阳黑子
    时间序列分析工具箱——sweep
    WebApi 找到了与该请求匹配的多个操作
    EF(EntityFramework)与mysql使用,错误终极解决方案
    EF(EntityFramework) 插入或更新数据报错
    EF(EntityFramework)与mysql使用,取数据报错,linq实体映射错误
    EF(EntityFramework)与mysql使用,序列化问题[System.ObjectDisposedException]
    EF(EntityFramework)与mysql使用,乱码问题
    c# AutoMapper 使用方式
    c# json 序列化时遇到错误 error Self referencing loop detected for type
  • 原文地址:https://www.cnblogs.com/Stomach-ache/p/4135896.html
Copyright © 2020-2023  润新知