hdu4607Park Visit 树的直径

时间:2021-07-30 20:31:16

//给一棵双向树,数中边的权值为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[maxn] ;

struct Edge

{

    int v ;

    int next ;

}edge[maxn*2] ;

int nedge ;

void addedge(int u , int v)

{

    edge[nedge].v = v ;

    edge[nedge].next = head[u] ;

    head[u] = nedge++ ;

    edge[nedge].v = u ;

    edge[nedge].next = head[v] ;

    head[v] = nedge++ ;

}

queue<int>que ;

int ma = 0 ;

int bfs(int st)

{

    while(que.size())que.pop() ;

    que.push(st) ;que.push(0) ;que.push(0) ;

    int pos ;

    while(que.size())

    {

        int u = que.front() ; que.pop() ;

        int step = que.front() ;que.pop() ;

        int pre = que.front() ; que.pop() ;

        if(step > ma)

        {

            ma = step ;

            pos = u ;

        }

        for(int i = head[u] ; i !=  -1 ;i = edge[i].next)

        {

            int v = edge[i].v ;

            if(v == pre)continue ;

            que.push(v);que.push(step+1);que.push(u) ;

        }

    }

    return pos ;

}

int main()

{

    int t ;

    scanf("%d" , &t) ;

    while(t--)

    {

        int n , m ;

        memset(head ,  -1 ,sizeof(head)) ;

        nedge = 0 ;

        scanf("%d%d" , &n , &m) ;

        for(int i = 1;i < n; i++)

        {

            int u  ,v ;

            scanf("%d%d" , &u , &v) ;

            addedge(u , v) ;

        }

        ma = 0 ;

        int pos = bfs(1) ;

        bfs(pos) ;

        while(m--)

        {

            int k ;

            scanf("%d" , &k) ;

            if(k <= ma+1)printf("%d\n" , k - 1) ;

            else printf("%d\n" , (k - (ma+1))*2+ma) ;

        }

    }

    return 0 ;

}