两次DFS求树直径方法见 这里。

这里的直径是指最长链包含的节点个数,而上一题是指最长链的路径权值之和,注意区分。

K <= R: ans = K − 1;

K > R:   ans = R − 1 + ( K − R ) ∗ 2;

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5
  6 using namespace std;
  7
  8 const int MAXN = 100010;
  9
 10 struct node
 11 {
 12     int v;
 13     int next;
 14 };
 15
 16 int N, Q, EdgeN;
 17 int head[MAXN];
 18 int best[MAXN];
 19 int dp[MAXN][3];
 20 node D[ MAXN << 1 ];
 21 bool vis[MAXN];
 22
 23 void AddEdge( int u, int v )
 24 {
 25     D[EdgeN].v = v;
 26     D[EdgeN].next = head[u];
 27     head[u] = EdgeN++;
 28     return;
 29 }
 30
 31 void DFS1( int u )
 32 {
 33     vis[u] = true;
 34     for ( int i = head[u]; i != -1; i = D[i].next )
 35     {
 36         int v = D[i].v;
 37         int w = 1;
 38         if ( !vis[v] )
 39         {
 40             DFS1( v );
 41             if ( dp[v][0] + w > dp[u][0] )
 42             {
 43                 dp[u][1] = dp[u][0];
 44                 dp[u][0] = dp[v][0] + w;
 45                 best[u] = v;
 46             }
 47             else if ( dp[v][0] + w > dp[u][1] )
 48                 dp[u][1] = dp[v][0] + w;
 49         }
 50     }
 51     return;
 52 }
 53
 54 void DFS2( int u )
 55 {
 56     vis[u] = true;
 57     for ( int i = head[u]; i != -1; i = D[i].next )
 58     {
 59         int fa = D[i].v;
 60         int w = 1;
 61         if ( !vis[fa] )
 62         {
 63             dp[fa][2] = dp[u][2] + w;
 64         if ( fa == best[u] )
 65             dp[fa][2] = max( dp[fa][2], dp[u][1] + w );
 66         else dp[fa][2] = max( dp[fa][2], dp[u][0] + w );
 67         DFS2( fa );
 68         }
 69     }
 70     return;
 71 }
 72
 73 int main()
 74 {
 75     int T;
 76     scanf( "%d", &T );
 77     while ( T-- )
 78     {
 79         scanf( "%d%d", &N, &Q );
 80         EdgeN = 0;
 81         memset( head, -1, sizeof(head) );
 82         for ( int i = 1; i < N; ++i )
 83         {
 84             int u, v;
 85             scanf( "%d%d", &u, &v );
 86             AddEdge( u, v );
 87             AddEdge( v, u );
 88         }
 89
 90         memset( dp, 0, sizeof(dp) );
 91         memset( vis, false, sizeof(bool) * (N + 1) );
 92         DFS1( 1 );
 93         memset( vis, false, sizeof(bool) * (N + 1) );
 94         DFS2( 1 );
 95
 96         int maxx = 0;
 97         for ( int i = 1; i <= N; ++i )
 98             maxx = max( maxx, max( dp[i][0], dp[i][2] ) );
 99         ++maxx;
100
101         while ( Q-- )
102         {
103             int K;
104             scanf( "%d", &K );
105             if ( maxx >= K )
106                 printf( "%d\n", K - 1 );
107             else printf( "%d\n", maxx - 1 + ( K - maxx ) * 2 );
108         }
109     }
110     return 0;
111 }

转载于:https://www.cnblogs.com/GBRgbr/p/3220455.html

HDU 4607 Park Visit 两次DFS求树直径相关推荐

  1. hdu 4607 Park Visit 求树的直径

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 Claire and her little friend, ykwd, are travelli ...

  2. HDU - 4607 Park Visit (树的直径)

    http://acm.hdu.edu.cn/showproblem.php?pid=4607 题意 一颗n个顶点的树,现在只想访问其中k个,问最短路径长度为多少. 分析 首先,最短的路径当然是一条链. ...

  3. HDU 4607 Park Visit(树的直径)

    题目大意:给定一棵树,让求出依次访问k个点的最小花费,每条边的权值都为1. 思路:如果能一直往下走不回来,那么这个路径肯定是最小的,这就取决于给定的k,但是怎么确定这个能一直走的长度呢,其实这个就是树 ...

  4. hdu 4607 Park Visit(树上最长链)

    求树上最长链:两遍搜索. 第一次从树上任意点开始,最远点必然是某一条最长链上的端点u. 第二次从u开始,最远点即该最长链的另一端点. 先在最长链上走,不足再去走支链. 把询问数m错打成n,狠狠wa了一 ...

  5. HDU 4607 Park Visit HDU暑期多校1

    10W个点的一棵树,边权为1 求访问K个点要走过的最小路程 BFS求出一条最长路以后,我们可以YY出其他的边都要重复走两次 树上的最长路可以从任意一点开始BFS求出这点的最大距离,再把终点设置为起点再 ...

  6. PAT甲级1021 Deepest Root :[C++题解]树的最大深度、并查集、dfs求树的深度

    文章目录 题目分析 题目链接 题目分析 分析: 考察知识点:并查集.dfs.树的深度 给定n个结点,n-1条边,只要能保证只有1个连通分量,就是一棵树.否则的话就不是树,它是不连通的. 用并查集来看是 ...

  7. acwing 1078. 旅游规划(求树直径上的点)

    题目链接 题意:给一个树,可能直径不唯一,求所有直径上的所有的点 思路: 这题刚开始以为可以两次bfs,第二次bfs的时候记录前驱暴力求解,结果tle了 = =.. 正确解法是,先用dp求直径,然后从 ...

  8. PAT甲级1053 Path of Equal Weight (30分) :[C++题解]dfs求树的路径长度、邻接表

    文章目录 题目分析 题目链接 题目分析 输入样例: 20 9 24 10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2 00 4 01 02 03 04 02 1 ...

  9. 求树的直径的两种方法

    树的直径 树型dp求树的直径 优缺点: 优点为可以处理边权为负的情况,但不易得到直径的路径(指树的直径经过什么点). 代码模板: #include<bits/stdc++.h> using ...

最新文章

  1. LoadRunner之二“集合点”
  2. 经典网络AlexNet介绍
  3. 人工智能 MIT 博士系列讲课
  4. python | gtts 将文字转化为语音内容
  5. Java中print、printf、println的区别 详解
  6. numpy.negative详解
  7. Deeplab 在Qt Creator下编译报错undefined reference to Mat_xxx
  8. scanf()的使用
  9. mac下查看redis安装路径_干货!win10环境下Redis安装、启动教程
  10. Cas单点登录配置数据查询用户
  11. shmget出现Invalid argument错误
  12. 酷狗显示服务器失败怎么回事,酷狗音乐上传音乐失败怎么回事
  13. RS编码过程通俗理解
  14. matlab设置等高线标注字体大小,matlab设置图中字体和线条大小等(转)
  15. 奥维地图从服务器获取信息超时,2021奥维地图不能用了原因及解决办法
  16. MOSS入门介绍 和 概念介绍
  17. 2549. 删除他们! 解题报告
  18. 【产品经理】AARRR模型
  19. 微信扫码签到系统asp源码2.0示例
  20. Unity 设置程序在后台运行

热门文章

  1. bboss es对比直接使用es客户端的优势
  2. Markdown符号:整除、不整除、恰整除、不恰整除
  3. C++动态分配内存空间
  4. 字节题--雀魂启动!
  5. windows系统vmware重装步骤
  6. 拼多多怎么设置快捷回复
  7. 【实用算法教学】——教你使用决策树算法预测NBA获胜球队
  8. FusionGAN:一种生成式红外与可见光图像融合对抗网络
  9. 谈论AI之前,你搞懂人类了吗?
  10. docker使用和搭建