HDU4607 - Park Visit(树的直径)

题目大意

给定一颗树,要求走过其中连续的k个点,使得步数最少

题解

每条边要么经过两次,要么一次,因为我们的目标就是使得走一次的边尽量的多,这样就转换成求树的直径了,求树的直径我用的是两次dfs,先随便从一个点开始dfs,找出以这个点为根距离它最远的结点,假设为s,然后再从s结点进行一个dfs,距离s结点最远的点与s点的距离就是树的直径(假设为d),最后判断一下k和树的直径的大小,如果k-1小于树的直径,那么直接输出k-1,否则答案就是d+(k-1-d)*2

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define  MAXN 100005
vector<int>ivec[MAXN];
int ret,sum;
void dfs(int k,int fa,int dis)
{
    if(dis>sum)
    {
        sum=dis;
        ret=k;
    }
    int len=ivec[k].size();
    for(int i=0; i<len; i++)
        if(ivec[k][i]!=fa) dfs(ivec[k][i],k,dis+1);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) ivec[i].clear();
        for(int i=1; i<n; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            ivec[u].push_back(v);
            ivec[v].push_back(u);
        }
        ret=1;
        sum=0;
        dfs(ret,0,0);
        dfs(ret,0,0);
        while(m--)
        {
            int k;
            scanf("%d",&k);
            if(k-1<=sum) printf("%d\n",k-1);
            else
                printf("%d\n",sum+(k-1-sum)*2);
        }
    }
    return 0;
}

posted on 2013-11-10 23:43  仗剑奔走天涯  阅读(228)  评论(0编辑  收藏  举报

导航