码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4607 Park visit (求树的直径)

时间:2015-07-19 11:55:17      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:

解题思路:

通过两次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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 4607 Park visit (求树的直径)

标签:

原文地址:http://blog.csdn.net/moguxiaozhe/article/details/46953315

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!