Codeforces 1004E

题意略。

思路:

这k个点应该放在这棵树的直径上,并且能连成一条路径。如果k比树的直径上的点要多,那么我们就不用把这k个点都用上,

只需要把这棵树直径上所有的点都覆盖上就行了。如果k比树的直径上的点要少,那么我们尽量使这k个点放在这个直径的中心位置。

                                                                         

这个我们可以简单说一下:

首先,把这k个点放在直径中央可以保证直径上的点到这段路径的最大距离最小。但是其他的枝叶呢,可以保证其他枝叶上的点到这一段路径的最大距离最小吗?

假设我为了迁就某个枝叶上的点,使得这段路径偏离了直径的中央,那么只能说明这段枝叶比原来接口处向外的那一部分直径还长,这是不可能的,

这只能说明这段枝叶是直径的一部分。

所以我们先找出直径,再寻找直径的中间位置,然后一遍dfs,确定整棵树上到这段路径的最远距离。

详见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;

struct edge{
    int to,w;
    edge(int a = 0,int b = 0){
        to = a,w = b;
    }
};

int deep[maxn],fa[maxn],store[maxn],tail,n,k;
vector<edge> graph[maxn];

void dfs(int node){
    for(int i = 0;i < graph[node].size();++i){
        edge e = graph[node][i];
        int to = e.to,w = e.w;
        if(fa[to] == 0){
            if(deep[to] == -1) deep[to] = deep[node] + w;
            fa[to] = node;
            dfs(to);
        }
    }
}

int main(){
    scanf("%d%d",&n,&k);
    int from,to,w;
    for(int i = 0;i < n - 1;++i){
        scanf("%d%d%d",&from,&to,&w);
        graph[from].push_back(edge(to,w));
        graph[to].push_back(edge(from,w));
    }
    memset(deep,-1,sizeof(deep));
    memset(fa,0,sizeof(fa));
    fa[1] = -1;
    deep[1] = 0;
    dfs(1);
    int ed1 = 1,ed2;
    for(int i = 1;i <= n;++i){
        if(deep[i] > deep[ed1]) ed1 = i;
    }
    memset(deep,-1,sizeof(deep));
    memset(fa,0,sizeof(fa));
    fa[ed1] = -1;
    deep[ed1] = 0;
    dfs(ed1);
    ed2 = ed1;
    for(int i = 1;i <= n;++i){
        if(deep[i] > deep[ed2]) ed2 = i;
    }
    int deepest = deep[ed2];
    for(int i = ed2;i != -1;i = fa[i]){
        store[tail++] = i;
    }
    
    int l,r;
    if(tail <= k) l = 0,r = tail - 1;
    else{
        int L = 0;
        for(int i = 0;i < tail - k + 1;++i){
            if(max(deepest - deep[store[i]],deep[store[i + k - 1]]) < max(deepest - deep[store[L]],deep[store[L + k - 1]]))
                L = i;
        }
        l = L,r = l + k - 1;
    }
    memset(deep,-1,sizeof(deep));
    memset(fa,0,sizeof(fa));
    fa[store[l]] = -1;
    for(int i = l;i <= r;++i){
        deep[store[i]] = 0;
    }
    dfs(store[l]);
    int ans = 0;
    for(int i = 1;i <= n;++i) ans = max(ans,deep[i]);
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/tiberius/p/9287703.html