题目描述
A new city has just been built. There're interesting places numbered by positive numbers from 1 to .
In order to save resources, only exactly roads are built to connect these 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 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 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.
备注
题目大意:
在一棵树上,有多个节点有人,要求选择一个节点,让所有人在这个节点相遇。相遇的时间规定为所有人中到达该节点所用的最长时间。要求给出最小的相遇时间。
分析:
考虑相距最远的两个人,那么两者路径的中点就是所有人的相遇点,这样能保证最小的相遇时间。这就类似于求树的直径,结果就是树的直径除以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;
}