zoukankan      html  css  js  c++  java
  • 某不知名的树形Dp

    题意

    给出一个(N)个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大

    分析

    看到树,还让求最大,这种可能不是贪心就是树形(DP),贪心的话树的形状没法判断,果断放弃,那么就只能是(DP)了。
    既然它让求深度之和,那么我就直接定义以(i)为根时深度和为(DP_i),接下来就是怎么转移的问题了。如果我枚举每个点来考虑,那么还要计算它下边的子树和它上边的子树,显然是不好弄,时间复杂度可能在(O(N^2))左右,虽然时间十秒但也不够用啊,由于(n)大到了1000000,所以这个题还是得用(O(n))的效率,如果我以某种手段得到了(DP_1),那么接下来的转移就好说了,每次往下找一个儿子(v),深度减小了(siz_v),增加了(n-siz_v),这样就能用两个(O(n))来完成这个题,最后在(O(n))的统计一下答案就好。
    (DP)数组要开(long long)

    #include<cstdio>
    using namespace std;
    const int N=1e6+10;
    struct Edge{
        int to,nxt;
    }e[N<<1];
    int dep[N],Head[N],len;
    void Ins(int a,int b){
        e[++len].to=b;e[len].nxt=Head[a];Head[a]=len;
    }
    int siz[N];
    long long dp[N];
    void dfs(int u,int fa){
        siz[u]=1;dp[u]=dep[u];
        for(int i=Head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(v==fa)continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
            siz[u]+=siz[v];
            dp[u]+=dp[v];
        }
    }    
    int n;
    void calc(int u,int fa){
        for(int i=Head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(v==fa)continue;
            dp[v]=dp[u]-siz[v]+n-siz[v];
            calc(v,u);
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            Ins(a,b);Ins(b,a);
        }
        dfs(1,0);
        calc(1,0);
        int ans=0;
        for(int i=1;i<=n;i++)
            if(dp[ans]<dp[i])ans=i;
        printf("%d
    ",ans);
    }
    

    总结

    转移方程题目问什么设什么先,求不出来再考虑换或者辅助一下(DP).

  • 相关阅读:
    Jquery:强大的选择器<一>
    要经营我的园子了!!!
    Json在Struts中的转换与传递
    MyEclipse快捷键大全
    Pyqt在QListWidget中添加右键菜单
    swift中Double转String
    Spring MVC 关于分页的简单实现
    Spring MVC 通过@Value注解读取.properties配置内容
    SQL 查询语句(备份)
    Idea使用说明
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12682898.html
Copyright © 2011-2022 走看看