Park Visit(树的直径)

传送门

Park Visit

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3721    Accepted Submission(s): 1667

Problem Description

Claire and her little friend, ykwd, are travelling in Shevchenko‘s Park! The park is beautiful - but large, indeed. N feature spots in the park are connected by exactly (N-1) undirected paths, and Claire is too tired to visit all of them. After consideration, she decides to visit only K spots among them. She takes out a map of the park, and luckily, finds that there‘re entrances at each feature spot! Claire wants to choose an entrance, and find a way of visit to minimize the distance she has to walk. For convenience, we can assume the length of all paths are 1.
Claire is too tired. Can you help her?

Input

An integer T(T≤20) will exist in the first line of input, indicating the number of test cases.
Each test case begins with two integers N and M(1≤N,M≤105), which respectively denotes the number of nodes and queries.
The following (N-1) lines, each with a pair of integers (u,v), describe the tree edges.
The following M lines, each with an integer K(1≤K≤N), describe the queries.
The nodes are labeled from 1 to N.

Output

For each query, output the minimum walking distance, one per line.

Sample Input

1
4 2
3 2
1 2
4 2
2
4

Sample Output

1
4

【题目大意】

在一棵树上 求经过k个点的最短路径。

【思路】

如果是最短路径的话 我们想一直走路径不重复就可以了。

求树的直径,如果要经过k个点的k<r 那么说明这k个点可以在一条线上进行,答案为k-1.

如果不行 肯定要走直径外的分支,不要考虑复杂走哪个分支,反正分支肯定走进去又走出来(继续走直径)

用公式算出来就行 自己推推吧。

我这个代码第二个样例没过,但是算出来就是4啊,但是A了。

【code】

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,k,x,y,sumedge,maxn,maxx,t;
int dad[100009],dis[100009],head[100009];
struct Edge
{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[200009];
void init()
{
    sumedge=0;
    memset(head,0,sizeof(head));
    memset(dad,0,sizeof(dad));
    memset(dis,0,sizeof(dis));
}
void add(int x,int y)
{
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}
void dfs(int x)
{
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].y;
        if(dad[x]!=v)
        {
            dad[v]=x;
            dis[v]=dis[x]+1;
            dfs(v);
        }
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        dfs(1);
        maxx=-0x7ffff;
        for(int i=1;i<=n;i++)
        {
            if(dis[i]>maxx)
            {
                maxx=dis[i];
                maxn=i;
            }
        }
        memset(dis,0,sizeof(dis));
        memset(dad,0,sizeof(dad));
        dfs(maxn);
        maxx=-0x7ffff;
        for(int i=1;i<=n;i++)
        {
            if(dis[i]>maxx)
            {
                maxx=dis[i];
            }
        }
        while(m--)
        {
            scanf("%d",&k);
            if(k<=maxx)
            printf("%d\n",k-1);
             else
             printf("%d\n",maxx+(k-maxx-1)*2);
         }
    }
    return 0;
}
时间: 2024-10-02 23:27:01

Park Visit(树的直径)的相关文章

HDU 4607 Park Visit(树的直径)

题目大意:给定一棵树,让求出依次访问k个点的最小花费,每条边的权值都为1. 思路:如果能一直往下走不回来,那么这个路径肯定是最小的,这就取决于给定的k,但是怎么确定这个能一直走的长度呢,其实这个就是树的直径,也叫作最长简单路径.找出来这个直径之后,只需和k比较一下就能确定走多少步.设直径为maxx, 如果maxx + 1== k的话,说明刚好不用回来走完最长的这个路,所以当k小于等于maxx + 1的时候就是k-1,当k大于maxx + 1的时候,除了要走完不用回来的路,肯定还要走那些用回来的,

hdu4607Park Visit 树的直径

//给一棵双向树,数中边的权值为1,问对于这颗树中走k个节点的最短路径 //如果k小于这颗数的直径加1,那么走k个节点就没有重复的路,如果大于 //那么大于的节点都需要走两遍 #include<cstdio> #include<cstring> #include<iostream> #include<queue> using namespace std ; const int maxn = 100010 ; int head[maxn] ; int vis[

HDU 4607 Park Visit 求树的直径

Park Visit Problem Description Claire and her little friend, ykwd, are travelling in Shevchenko's Park! The park is beautiful - but large, indeed. N feature spots in the park are connected by exactly (N-1) undirected paths, and Claire is too tired to

hdu 4607 Park Visit(树的直径)

Park Visit Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2506    Accepted Submission(s): 1128 Problem Description Claire and her little friend, ykwd, are travelling in Shevchenko's Park! The

HDU 4607 Park visit (求树的直径)

解题思路: 通过两次DFS求树的直径,第一次以任意点作为起点,找到距离该点距离最远的点,则可以证明这个点一定在树的直径上,然后以该点为起点进行DFS得到的最长路就是树的直径. 最后的询问,如果K <= D + 1则可以沿着直径走,距离为K  -  1, 如果K >= D + 1,则需要走直径旁边的分支,每访问一个点距离为2(从直径到这个点,再返回到直径上). #include <iostream> #include <cstring> #include <cstd

HDU4607 Park Visit(解法二)

问题链接:HDU4607 Park Visit. 题意简述:莱克尔和她的朋友到公园玩,公园很大也很漂亮.公园包含n个景点通过n-1条边相连.克莱尔太累了,所以不能去参观所有点景点.经过深思熟虑,她决定只访问其中的k个景点.她拿出地图发现所有景点的入口都很特殊.所以她想选择一个入口,并找到一条最短的路来参观k个景点.假设景点之间的距离为1. 输入数据:先输入测试用例数t,每个测试用例数据包括N和M,N为节点数,M为需要查询的上述的k(参观M个景点). 输出数据:对于各个M,输出需要走的距离. 问题

Park Visit

hdu4607:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题意:给你一棵树,树上每条边的权值是1,然后然你选择m个点,求遍历m个点的最小花费. 题解:这一题要用到树的性质.首先可以想到的是第一次肯定要选择一条最长的路径,也就是树的直径.至于其余的点怎么考虑呢?画个图可以知道,剩余的点的所产生的花费就是剩余点数的两倍,所以本题的关键就是求树的直径.求树的直径,是有方式的,就是两遍DFS,第一遍DFS找到一个当前点的最远的点,然后从这个最远的点开始

HDU4607 Park Visit

问题链接:HDU4607 Park Visit. 问题简述:莱克尔和她的朋友到公园玩,公园很大也很漂亮.公园包含n个景点通过n-1条边相连.克莱尔太累了,所以不能去参观所有点景点.经过深思熟虑,她决定只访问其中的k个景点.她拿出地图发现所有景点的入口都很特殊.所以她想选择一个入口,并找到一条最短的路来参观k个景点.假设景点之间的距离为1. 输入数据:先输入测试用例数t,每个测试用例数据包括N和M,N为节点数,M为需要查询的上述的k(参观M个景点). 输出数据:对于各个M,输出需要走的距离. 问题

题解报告:hdu 4607 Park Visit(最长路+规律)

Problem Description Claire and her little friend, ykwd, are travelling in Shevchenko's Park! The park is beautiful - but large, indeed. N feature spots in the park are connected by exactly (N-1) undirected paths, and Claire is too tired to visit all