题意 :
n个节点,有k个人,求k个人到某一个节点的最短时间
题解:
考虑距离最远的两个关键点,设它们的距离为d,d/2上取整即为答案。
必要性:这两个人要碰面,必然要走至少d/2步。
充分性:我们取两人路径中和一头距离为d/2上取整的一个点,让所有人在这相聚。如 果有一个人在d/2时间内到不了,那么它和路径两头中与它远的那一头的距离大于d,与 最远的假设矛盾。
从任意一个关 键点开始,找到离它最远的关键点x,再从 x 开始dfs,找到的新的最远点和 x 形成的就是直径。
#include <bits/stdc++.h>
using namespace std;
vector<int> a[100005];
int v[100005], top, sum = 0;
void dfs(int p, int f, int step){
if(v[p] && step > sum){
top = p;
sum = step;
}
for(int i = 0; i < a[p].size(); i++){
if(a[p][i] != f){
dfs(a[p][i], p, step+1);
}
}
}
int main(){
int n, k, x, y, t;
cin >> n >> k;
for(int i = 1; i < n; i++){
cin >> x >> y;
a[x].push_back(y);
a[y].push_back(x);
}
memset(v, 0, sizeof(v));
for(int i = 1; i <= k; i++){
cin >> t;
v[t] = 1;
}
dfs(t, 0, 1);
dfs(top, 0, 1);
cout << sum/2 << endl;
return 0;
}