• 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;
    }
  • 相关阅读:
    各类Http请求状态(status)及其含义 速查列表 xmlhttp status
    Microsoft Visual Studio 2010 正式版下载[含旗舰版序列号](中、英文版)
    【分享】开源或免费的ASP.NET web应用列表
    线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析
    Asp.Net中多语言的实现
    Oracle 数字与空值的排序问题
    新版微软一站式示例代码库 6月2日更新下载。
    .NET反射机制简介
    Decimal与double类型误差
    用动态菜单增强.NET应用程序
  • 原文地址:https://www.cnblogs.com/tiberius/p/9287703.html
Copyright © 2020-2023  润新知