HDU 4607 Park visit (求树的直径)
2024-08-26 00:29:51
解题思路:
通过两次DFS求树的直径,第一次以随意点作为起点,找到距离该点距离最远的点,则能够证明这个点一定在树的直径上,然后以该点为起点进行DFS得到的最长路就是树的直径。
最后的询问,假设K <= D + 1则能够沿着直径走,距离为K - 1, 假设K >= D + 1。则须要走直径旁边的分支,每訪问一个点距离为2(从直径到这个点,再返回到直径上)。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#define LL long long
using namespace std;
const int MAXN = 100000 + 10;
struct Edge
{
int to, next;
}edge[2 * MAXN];
int tot;
int head[MAXN];
int dis[MAXN];
int N, M;
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int dfs(int u, int pre = -1)
{
int ans = u;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v = edge[i].to;
if(v == pre) continue;
dis[v] = dis[u] + 1;
int dv = dfs(v, u);
if(dis[ans] < dis[dv]) ans = dv;
}
return ans;
}
int solve(int u)
{
dis[u] = 0;
u = dfs(u);
dis[u] = 0;
return dis[dfs(u)];
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &N, &M);
init();
int u, v;
for(int i=1;i<N;i++)
{
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
int D = solve(1);
for(int i=1;i<=M;i++)
{
int K;
scanf("%d", &K);
if(K <= D + 1) cout << K - 1 << endl;
else cout << D + (K - D - 1) * 2 << endl;
}
}
return 0;
}
最新文章
- ubuntu安装pppoeconf后与networkmanager冲突
- 关于 Graph Convolutional Networks 资料收集
- VC++ 将资源位图画到窗口上去的方法
- Docker初步认识安装和简单实例
- SymmetricDS文档翻译--【Chapter 3. 具体配置(Configuration)[section C]】
- Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->;wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)
- CSS学习笔记之元素分类
- insertBefore 和 insetAfter函数详解
- 使用Git与Github创建自己的远程仓库
- web缓存之--http缓存机制
- ASP.NET MVC5多语言切换快速实现方案
- Log4j分级别保存日志到单个文件中,并记录IP和用户信息
- Invalid character found in the request target.
- JMeter命令行参数汇总
- MATLAB indexing question
- 转:cookie.setPath()用法
- 20165336 2017-2018-2 《Java程序设计》第7周学习总结
- ZOJ - 4089 :Little Sub and Isomorphism Sequences (同构 set)
- bzoj4933: 妙
- VSCode和VUE的初始安装及简单使用入门