zoukankan      html  css  js  c++  java
  • 【BashuOJ2397】计算机网络-树形DP

    测试地址:计算机网络
    题目大意:给定一棵边权均为1的树,求每个点到其他点距离最大值的最小值。
    做法:这是一道树形DP的题目。
    考虑每一个点,我们显然可以用一次树形DP求出它到它子树中点的距离最大值,以下称为最长链,那么怎么求它到其他点距离的最大值呢?对于它的每个祖先,有两种情况:
    1.这个祖先的最长链不经过子树中包含该点的那个儿子,那么这种情况下该点经过这个祖先到达其他点的最大距离就是该点到祖先的距离+祖先的最长链
    2.这个祖先的最长链经过子树中包含该点的儿子,那么这种情况下该点经过这个祖先到达其他点的最大距离就是该点到祖先的距离+祖先的次长链。注意这里的次长链是指去掉最长链之后的次长,而不是指可能和最长链部分重合的真正的次长链。
    那是不是我们每访问一个点,都要再访问一遍它的所有祖先呢?没有必要,我们可以在函数中传递一个参数maxlen,表示该点经过它祖先到达其他点的最大值,如果mx(v)smx(v)分别表示点v的最长链和次长链,那么我们从点v向下访问时,maxlen应该根据情况变为max(maxlen+1,mx(v)+1)max(maxlen+1,smx(v)+1)。之所以要加1,是因为要算上从点v下去的那条边。最后再统计每个点到其他点距离最大值的最小值就可以了。时间复杂度为O(n)
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define inf 1000000000
    using namespace std;
    int n,ans=inf,mx[10010]={0},smx[10010]={0},mxp[10010]={0},t[10010];
    int first[10010]={0},tot=0;
    struct edge {int v,next;} e[20010];
    
    void insert(int a,int b)
    {
        e[++tot].v=b;
        e[tot].next=first[a];
        first[a]=tot;
    }
    
    void dp(int v,int f)
    {
        for(int i=first[v];i;i=e[i].next)
            if (e[i].v!=f)
            {
                dp(e[i].v,v);
                if (mx[e[i].v]+1>=mx[v])
                {
                    smx[v]=mx[v];
                    mx[v]=mx[e[i].v]+1;
                    mxp[v]=e[i].v;
                }
                else if (mx[e[i].v]+1>=smx[v]) smx[v]=mx[e[i].v]+1;
            }
    }
    
    void dfs(int v,int f,int mxlen)
    {
        t[v]=max(mxlen,mx[v]);
        ans=min(ans,t[v]);
        for(int i=first[v];i;i=e[i].next)
            if (e[i].v!=f)
            {
                if (e[i].v==mxp[v]) dfs(e[i].v,v,max(mxlen+1,smx[v]+1));
                else dfs(e[i].v,v,max(mxlen+1,mx[v]+1));
            }
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            insert(a,i),insert(i,a);
        }
    
        dp(1,0);
        dfs(1,0,0);
        for(int i=1;i<=n;i++)
            if (t[i]==ans) printf("%d ",i);
    
        return 0;
    }
    
  • 相关阅读:
    03-串联
    大数据项目之电商数仓(3电商数据仓库系统)V6.1.3
    JQuery实现tab页
    Java面试题之计算字符/字符串出现的次数
    ios 苹果内购订单验证 --- nodejs实现
    ios 苹果内购订单验证 --- php实现
    Android内购订单验证 --- nodejs实现
    Android内购订单验证 --- php实现
    Google Compute Engine VM自动调节
    php性能优化 --- laravel 性能优化
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793592.html
Copyright © 2011-2022 走看看