zoukankan      html  css  js  c++  java
  • Bzoj 1131[POI2008]STA-Station (树形DP)

    Bzoj 1131[POI2008]STA-Station (树形DP)

    状态:
    (f[i])为以(i)为根的深度之和,然后考虑从他父亲转移.
    发现儿子的深度及其自己的深度(-1)
    其余的(+1),记录一下(size)就ok了
    转移:
    (f[i] = f[fa] + n - 2 * size[i])
    记忆化搜索即可.
    Bzoj 可能过不了,原因貌似是栈空间不足,可以去洛谷提交,我这里的解决方法是.记忆化搜索的时候用(n)作为开头.然后就过了.

    #include <iostream>
    #include <cstdio>
    #define ll long long
    const int maxN = 1000000 + 7;
    
    ll f[maxN],n; // f[i] = f[fa] + n - 2 * size[i];
    int size[maxN],dep[maxN],fa[maxN];
    
    struct Node {
        int v,nex;
    }Map[maxN << 1];
    int head[maxN],num;
    
    inline int read() {
        int x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
        while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
        return x * f;
    }
    
    inline ll max(ll a,ll b) {return a > b ? a : b;}
    
    void add_Node(int u,int v) {
        Map[++ num] = (Node) {v,head[u]};
        head[u] = num;
        return ; 
    }
    
    void work_fst(int now) {
        size[now] = 1;dep[now] = dep[fa[now]] + 1;
        for(int i = head[now];i;i = Map[i].nex) {
            int v = Map[i].v;
            if(v != fa[now]) {
                fa[v] = now;
                work_fst(v);
                size[now] += size[v];
            }
        }
        return ;
    }
    
    void work_dp(int now) {
        for(int i = head[now];i;i = Map[i].nex) {
            int v = Map[i].v;
            if(v != fa[now]) {
                f[v] = f[now] + n - 2 * size[v];
                work_dp(v);
            }
        }
    }
    
    int main() {
        n = read();
        for(int i = 1,u,v;i < n;++ i) {
            u = read();v = read();
            add_Node(u,v);
            add_Node(v,u);
        }
        dep[0] = -1;
        work_fst(n);
        for(int i = 1;i <= n;++ i)
            f[n] += dep[i];
        work_dp(n);
        ll ans = 0;
        for(int i = 1;i <= n;++ i)
            ans = max(ans,f[i]);
        for(int i = 1;i <= n;++ i)
            if(f[i] == ans) {printf("%d
    ", i);break;}
        return 0;
    }
    
  • 相关阅读:
    怎样创建动态扩容数组?
    怎样终止一个线程?
    模式识别
    基于Linux根据僵尸网络病毒平台《比尔盖茨》
    web.xml在&lt;init-param&gt;一个错误
    DTD学习笔记
    Java排序算法(四):Shell排序
    VC6迁移到VS2008几个问题——良好的代码,从我做起,从现在开始。
    Maven 建 Struts2 基本实现 CURD Controller
    Andy&#39;s First Dictionary
  • 原文地址:https://www.cnblogs.com/tpgzy/p/9758845.html
Copyright © 2011-2022 走看看