首页 > 其他分享 >洛谷 p5536 题解

洛谷 p5536 题解

时间:2023-01-05 13:57:44浏览次数:64  
标签:maxDeep 洛谷 int 题解 dfs vector p5536 include dist

题目链接:https://www.luogu.com.cn/problem/P5536
此题为树的dfs的一个应用。

思路

  1. 树 dfs时,可以计算每个点的深度。
    如图所示
  2. 可以多次dfs,从而找到不同的信息。

代码片断

  1. 2次dfs找直径/中心
int maxLen = INT_MIN;//直径
int q;//最远点
vector<int> dist(n+1);//每个点的深度
vector<int> pathPrev(n+1);//直径找父
function<void(int, int)> dfs = [&](int u, int fa) {
    for (auto v : G[u]) {
        if (v == fa)continue;
        dist[v] = dist[u] + 1;
        pathPrev[v] = u;
        if (maxLen < dist[v]) { maxLen = dist[v]; q = v; }
        dfs(v, u);
    }
};
dfs(1, 0);//任意点找最远点
int ret1 = q;
dist[q] = 0;
maxLen = INT_MIN;
dfs(q, 0);//最远点找另一最远点
  1. 找直径中心
int midPoint = q;
for (int i = 0; i < (maxLen+1)/ 2; ++i) 
  midPoint = pathPrev[midPoint];
  1. 每个点到叶子点的最远距离
vector<int> maxDeep(n + 1);//当前点能到达的最大深度
vector<int> deep(n + 1);   //当前点的深度  这个与前面的dist意义相同
vector<int> eachPointToLeafLen(n+1);
function<void(int, int)>  dfs3= [&](int u, int fa) {
  maxDeep[u] = deep[u];
  for (auto v : G[u]) {
    if (v != fa) continue;
    deep[v] = deep[u] + 1;//子点的深度
    dfs3(v, u);
    maxDeep[u] = max(maxDeep[u],maxDeep[v]);//此点最深由子深决定
  }
  eachPointToLeafLen[u] = (maxDeep[u] - deep[u]);//此点到最深的叶子长度
};
dfs3(midPoint, -1);

完整代码

#include <iostream>
#include <cassert>
#include <iomanip>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <climits>
#include <functional>
#include <list>
#include <cstdlib>
#include <set>
#include <stack>
#include <sstream>
#include <numeric>
#include <map>
#include <algorithm>
#include <bitset>

#define endl "\n"
#define i64 long long
#define ui64 unsigned long long
#define INF 0x3f3f3f3f
#define MZ(arr) memset(arr,0,sizeof(arr))
#define MS(arr,val) memset(arr,val,sizeof(arr))



using namespace std;

namespace SLOVER {
    void slove() {
        int n, k,u,v;
        cin >> n >> k;
        vector<vector<int>> G(n + 1);
        for (int i = 1; i < n; ++i) {
            cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
      vector<int> pathPrev(n+1);

      int maxLen = INT_MIN;
      int q;
      vector<int> dist(n+1);
      auto dfs2FindDiameter = [&]() {
        function<void(int, int)> dfs = [&](int u, int fa) {
          for (auto v : G[u]) {
            if (v != fa) {
              dist[v] = dist[u] + 1;
              pathPrev[v] = u;
              if (maxLen < dist[v]) {
                maxLen = dist[v];
                q = v;
              }
              dfs(v, u);
            }
          }
        };
        dfs(1, 0);
        int ret1 = q;
        dist[q] = 0;
        maxLen = INT_MIN;
        dfs(q, 0);
      };

      dfs2FindDiameter();

    int midPoint = q;
    for (int i = 0; i < (maxLen+1)/ 2; ++i) {
      midPoint = pathPrev[midPoint];
    }

    vector<int> maxDeep(n + 1);//当前点能到达的最大深度
    vector<int> deep(n + 1);//当前点的深度
    vector<int> eachPointToLeafLen;
    function<void(int, int)> calcDeep = [&](int u, int fa) {
      maxDeep[u] = deep[u];
      for (auto v : G[u]) {
        if (v != fa) {
          deep[v] = deep[u] + 1;
          calcDeep(v, u);
          maxDeep[u] = max(maxDeep[u],maxDeep[v]);
        }
      }
      eachPointToLeafLen.push_back(maxDeep[u] - deep[u]);
    };
    calcDeep(midPoint, -1);
    sort(eachPointToLeafLen.begin(), eachPointToLeafLen.end(), std::greater<int>());

    int ret = 0;
    for (int i = k; i < n; ++i)ret = max(ret, eachPointToLeafLen[i] + 1);
    cout << ret << endl;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int  t = 1;
    while (t--) { SLOVER::slove(); }
    return 0;
}

标签:maxDeep,洛谷,int,题解,dfs,vector,p5536,include,dist
From: https://www.cnblogs.com/kingbuffalo/p/17027323.html

相关文章

  • CF513F2 题解
    题意传送门有\(a+b+1\)个会动的棋子,在一个大小为\(n\timesm\)的棋盘上,棋盘上有一些点有障碍。棋子中,有\(a\)个红色棋子,\(b\)个蓝色棋子,和\(1\)个既能当作红棋......
  • Codeforces Round #839 (Div. 3)题解
    C.DifferentDifferences(贪心)题意​ 给定\(k\),\(n\)\((2\lek\len\le40)\)。从\([1-n]\)中不重复地任选\(k\)个数组成一个数组,使这个数组的差分数组中不同的......
  • 【题解】CF700E Cool Slogans
    原题面很简洁,懒得概括了。思路后缀自动机+结论。这种题出题人没有十年脑血栓都没法出。结论1:\(s_{i-1}\)必定是\(s_i\)的后缀。考虑\(s_i\)中\(s_{i-1......
  • 【题解】CF1073G Yet Another LCP Problem
    题面很清楚,不概括了。思路后缀树+树剖。套路题。看到lcp考虑转化成后缀树上求lca,这里可以用SAM构造反串的parenttree解撅(f**kuukk)于是问题转化成:每次给......
  • 【题解】CF808E Selling Souvenirs
    题意多重背包,但数据范围很大并且体积小于等于三。思路乱搞。很自然地考虑将物品按照体积分成三类。显然对于同一类的物品从最大开始取最优,那么有一个贪心的想法。直......
  • 【题解】P5305 [GXOI/GZOI2019]旧词
    题面很清楚,不概括题意了。思路树剖。\(k=1\)的情况是P4211[LNOI2014]LCA具体来说,只需要\(\forall1\leqi\leqx\),将\(1\)到\(i\)的路径上每一个结点权值......
  • 题解 校内考20230104 T2 旗木双翼
    题目描述菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束。落子......
  • 洛谷表情包(仅供参考)
    ![](//图.tk/0)![](//图.tk/1)![](//图.tk/2)![](//图.tk/3)![](//图.tk/4)![](//图.tk/5)![](//图.tk/6)![](//图.tk/7)![](//图.tk/8)![](//图.tk/9)![](//图.......
  • LOJ 数列分块入门 9 题解题报告
    LOJ数列分块入门9题解题报告\(\text{ByDaiRuiChen007}\)I.数列分块入门1题目大意\(\text{Link}\)维护一个长度为\(n\)的序列,支持区间加,单点查值思路分析简......
  • 洛谷P1048 典型01背包问题
    写在前面的话蒟蒻在学习诸多图论算法之前,实际上没学过dp!强说是学过也是只学了01背包,今天就来温习一下……DP是啥?动态规划(DynamicProgramming,DP)是运筹学的一个分支,是......