![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f759566b822dfda9c5542a861bf53687.png)
题意
- 就是给你一棵树,以及
k
k
k个人的位置,让你在树上找一个点,是的所有人到这个点的最长的最短路径最小
题解
- 考虑树形
d
p
dp
dp,每个节点维护两个值,第一个是以该节点为根节点的子树中的人到该节点的最远距离,第二个是维护出去以该节点为根节点的子树的节点的到该节点最远距离信息,两个取
m
a
x
max
max,然后对答案取
m
i
n
min
min就行了
- 打完比赛发现大佬们都是写的树直径,就是求这
k
k
k个人中最远的那两个人的距离除以二向上取整就行了,可以反证法简单证明一下这种做法是对的
dp代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int dp[2][maxn],n,k,a,ans=10000000;
vector<int> vec[maxn];
set<pair<int,int> > s;
void solve(int cur,int fa)
{
int res=0;
res=max(res,dp[1][cur]);res=max(res,dp[0][cur]);ans=min(ans,res);
s.insert(make_pair(dp[1][cur]+1,cur));
for(int i=0;i<vec[cur].size();i++){
if(vec[cur][i]!=fa&&dp[0][vec[cur][i]]!=-1) {
s.insert(make_pair(dp[0][vec[cur][i]]+2,vec[cur][i]));
}
}
for(int i=0;i<vec[cur].size();i++) {
if(vec[cur][i]!=fa) {
if(dp[0][vec[cur][i]]!=-1) s.erase(make_pair(dp[0][vec[cur][i]]+2,vec[cur][i]));
auto big=(*s.rbegin());
dp[1][vec[cur][i]]=(big.first==0?-1:big.first);
if(dp[0][vec[cur][i]]!=-1) s.insert(make_pair(dp[0][vec[cur][i]]+2,vec[cur][i]));
}
}
s.clear();
for(int i=0;i<vec[cur].size();i++) if(vec[cur][i]!=fa) solve(vec[cur][i],cur);
}
void dfs(int cur,int fa)
{
for(int i=0;i<vec[cur].size();i++) {
if(vec[cur][i]!=fa) dfs(vec[cur][i],cur);
}
for(int i=0;i<vec[cur].size();i++) {
if(vec[cur][i]!=fa&&dp[0][vec[cur][i]]!=-1) dp[0][cur]=max(dp[0][cur],dp[0][vec[cur][i]]+1);
}
}
int main()
{
scanf("%d %d",&n,&k);ans=10000000;
memset(dp,-1,sizeof(dp));
for(int i=1,u,v;i<n;i++) {
scanf("%d %d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
for(int i=1;i<=k;i++) scanf("%d",&a),dp[0][a]=dp[1][a]=0;
dfs(1,0);
solve(1,0);
printf("%d\n",ans);
}
树直径代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,k,a[maxn];
vector<int> vec[maxn];
pair<int,int> dfs(int cur,int fa,int dis)
{
pair<int,int> res={0,0};
if(a[cur]) res={dis,cur};
for(int i=0;i<vec[cur].size();i++) if(vec[cur][i]!=fa){
auto k=dfs(vec[cur][i],cur,dis+1);
if(k.first>res.first) res=k;
}
return res;
}
int main()
{
scanf("%d %d",&n,&k);
for(int i=1,u,v;i<n;i++) {
scanf("%d %d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
for(int i=1,u;i<=k;i++) scanf("%d",&u),a[u]=1;
auto from=dfs(1,0,0);
auto to=dfs(from.second,0,0);
printf("%d\n",(to.first+1)/2);
}