2019牛客暑期多校训练营(第四场) A meeting 【树的直径】

题目描述

A new city has just been built. There're n interesting places numbered by positive numbers from 1 to n.

In order to save resources, only exactly n-1 roads are built to connect these n interesting places. Each road connects two places and it takes 1 second to travel between the endpoints of any road.

There is one person in each of the places numbered x_1,x_2...x_k and they've decided to meet at one place to have a meal. They wonder what's the minimal time needed for them to meet in such a place. (The time required is the maximum time for each person to get to that place.)

输入描述 

First line two positive integers, n,k - the number of places and persons.

For each the following n−1 lines, there're two integers a,b that stand for a road connecting place a and b. It's guaranteed that these roads connected all n places.

On the following line there're k different positive integers x_1,x_2...x_k​ separated by spaces. These are the numbers of places the persons are at.

输出描述 

A non-negative integer - the minimal time for persons to meet together.

示例输入 

4 2
1 2
3 1
3 4
2 4

示例输出 

2

说明 

They can meet at place 1 or 3.

备注 

1\leqslant n\leqslant 10^5

题目大意:

在一棵树上,有多个节点有人,要求选择一个节点,让所有人在这个节点相遇。相遇的时间规定为所有人中到达该节点所用的最长时间。要求给出最小的相遇时间。

分析:

考虑相距最远的两个人,那么两者路径的中点就是所有人的相遇点,这样能保证最小的相遇时间。这就类似于求树的直径,结果就是树的直径除以2然后向上取整。这里用两遍BFS求直径,但要注意在遍历的过程中只用有人的节点的深度去更新直径,这样求出来的就是有人的节点之间的最远距离。

具体解释见代码。

#include<stdio.h>

#include<string.h>

#include<queue>

#define MAX 200005

using namespace std;

int head[MAX];

int vis[MAX];//在BFS中,标记当前节点是否已经用过 

int dis[MAX];//记录最长距离(即节点的深度) 

int signal[MAX];//标志哪些点有人 

int n,m,ans;

int sum;//记录有人的节点之间最长路径的长度 

int lst;//记录最长路径的终点节点 

struct node

{

    int u,v,w;

    int next;

}edge[MAX];

void add(int u,int v,int w)//向邻接表中加边 

{

    edge[ans].u=u;

    edge[ans].v=v;

    edge[ans].w=w;

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

    head[u]=ans++;

}

void getmap()

{

    int i,j;

    int a,b,c;

    ans=0;

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

    while(m--)

    {

        scanf("%d%d",&a,&b);

        add(a,b,1);

        add(b,a,1);

    }

}

void bfs(int beg)

{

    queue<int>q;

    memset(dis,0,sizeof(dis));

    memset(vis,0,sizeof(vis));

    int i,j;

    while(!q.empty())

        q.pop();

    lst=beg;//终点初始化为起点 

    sum=0;

    vis[beg]=1;

    q.push(beg);

    int top;

    while(!q.empty())

    {

        top=q.front();

        q.pop();

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

        {

            if(!vis[edge[i].v])

            {

                dis[edge[i].v]=dis[top]+edge[i].w;//更新节点深度 

                vis[edge[i].v]=1;

                q.push(edge[i].v);

                if(signal[edge[i].v]&&sum<dis[edge[i].v])//只有当该节点有人,才会用该节点的深度去更新最长路径的值 

                {

                    sum=dis[edge[i].v];
                    
                    lst=edge[i].v;

                } 

            }

        }

    }

}

int main()

{


    int n,k,i; 
	
    scanf("%d%d",&n,&k);
	
    m=n-1;
	
    getmap();
    
    int a;
	
    for(i=1;i<=k;i++)
    {
		
	scanf("%d",&a); 
		 
	signal[a]=1;
		
    } 

    bfs(a);//从某一个有人的节点开始,搜索最长路径的一个端点 

    bfs(lst);//搜索另一个端点 

    printf("%d\n",(sum+1)/2);//最长路径的一半上取整 

    return 0;

}
发布了30 篇原创文章 · 获赞 5 · 访问量 900

猜你喜欢

转载自blog.csdn.net/qq_42840665/article/details/97802396
今日推荐