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

题目链接:https://ac.nowcoder.com/acm/contest/884/A

题意:给你一棵树,n个点,其中有k个点,每个点有1个人,  问如何 选择1~n中的一个合适的点让k个人聚在一起,使得最后一个人到达此点的时间最短,求出最短时间(经过一个点花费1单位时间)

最短时间必定是   选择好一点之后使得所有的人离得这个点越近越好,那么假设k=n,所以所有点都有人,则树的直径上的两个端点(或者其中的某一个)一定是距离选定的点最远的点,其他点到选定的点之间的距离一定小于等于直径的端点离选定的点的距离,那么只要求出直径的长度,然后除2向上取整就行了

为什么要向上取整呢,比如1   4  是直径的两个端点,然而直径的长度为3 ,因为你不能选择在路上相聚,只能选择一个点,所以

要么选择的点离1近,那么4到这个点的距离就为2  ; 反之 1离这个点的距离为2;总之结果都是2,所以需要向上取整

 

#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int maxn = 1e6+6;
int n,k;
struct node {
    int to,w;
};
int b[maxn],dp[maxn];
vector<node> v[maxn];

inline void dfs(int x,int fa) {
    for(int i=0;i<v[x].size();i++) {
        int to = v[x][i].to;
        if(to==fa) continue;
        dp[to]=dp[x]+1;
        dfs(to,x);
    }
}
int main()
{
    while(~scanf("%d%d",&n,&k)) {
        for(int i=1;i<=n;i++)v[i].clear();
        for(int i=1;i<n;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            v[x].push_back(node{y,1});
            v[y].push_back(node{x,1});
        }
        for(int i=1;i<=k;i++) {
            scanf("%d",&b[i]);
        }
        dfs(b[1],-1);
        int ans=0,st=b[1];
        for(int i=1;i<=k;i++){
            if(dp[b[i]]>ans) {
                ans=dp[b[i]];
                st=b[i];
            }
        }
        for(int i=1;i<=n;i++)dp[i]=0;
        dfs(st,-1);
        ans=0;
        for(int i=1;i<=k;i++){
            if(dp[b[i]]>ans) {
                ans=dp[b[i]];
            }
        }
        printf("%d\n",(ans+1)>>1);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值