zoukankan      html  css  js  c++  java
  • [USACO10MAR]伟大的奶牛聚集

    [USACO10MAR]伟大的奶牛聚集

    首先要想到(dp)转移方程,设(g[v])为设(v)为牛棚的花费,可以由其父亲转移而来

    [g[v]=g[u]-sz[v]*w+(tot-sz[v])*w ]

    之后我们随便制定一个树根算出初态(比如设定(1)为树根初态)即可开始转移

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define MAXN 100010
    #define ll long long
    ll f[MAXN];
    ll g[MAXN];
    int head[MAXN],nxt[MAXN*2],vv[MAXN*2],ww[MAXN*2],tot;
    inline void add_edge(int u, int v, int w){
        vv[++tot]=v;
        ww[tot]=w;
        nxt[tot]=head[u];
        head[u]=tot;
    }
    int sz[MAXN];
    int c[MAXN];
    void dfs(int u, int fa){
        sz[u]=c[u];
        for(int i=head[u];i;i=nxt[i]){
            int v=vv[i],w=ww[i];
            if(v==fa) continue;
            dfs(v, u);
            sz[u]+=sz[v];
            f[u]+=f[v]+(ll)sz[v]*w;
        }
    }
    const ll INF=1e18;
    ll ans=INF;
    void dfs2(int u, int fa){
        for(int i=head[u];i;i=nxt[i]){
            int v=vv[i],w=ww[i];
            if(v==fa) continue;
            g[v]=g[u]+(ll)w*(sz[1]-sz[v])-(ll)sz[v]*w;
            ans=min(ans, g[v]);
            dfs2(v, u);
        }
    }
    int n;
    int main(){
        scanf("%d", &n);
        for(int i=1;i<=n;++i) scanf("%d", &c[i]);
        for(int i=1;i<n;++i){
            int u,v,w;scanf("%d %d %d", &u, &v, &w);
            add_edge(u, v, w);
            add_edge(v, u, w);
        }
        dfs(1,1);
        g[1]=f[1];
        ans=min(ans, g[1]);
        dfs2(1, 1);
        printf("%lld
    ", ans);
        return 0;
    }
    /*
     f[u]+=f[v]+sz[v]*w
     g[v]=g[u]+w*(cnt-sz[v])-sz[v]*w
     */
    
    
  • 相关阅读:
    时空权衡之计数排序
    何时发生隐式类型转换
    常量指针与指针常量的区别
    虚函数有关面试题
    C++中数组定义及初始化
    InputStream类的available()方法
    FORK()函数
    面向对象三大基本特性,五大基本原则
    SpringMVC工作原理
    java文件的上传
  • 原文地址:https://www.cnblogs.com/santiego/p/11858189.html
Copyright © 2011-2022 走看看