zoukankan      html  css  js  c++  java
  • 【BZOJ】1827: [Usaco2010 Mar]gather 奶牛大集会(树形dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1827

    仔细想想就好了,,

    每个点维护两个值,一个是子树的费用,一个是除了子树和自己的费用。都可以用dfs做。

    维护第一个就是简单的dp。d1[i]=sum{d1[j]+w(i, j)*son1[j]},j是i的子女

    第二个就有些麻烦,因为要考虑的不只是这个点的父亲,还要考虑这个点父亲的子树。

    那么

    d2[i]=d2[fa]+w(fa, i)*son1[i]+d1[fa]-d1[i]

    而在处理这些方程有一些细节,不一定完全和上边的的方程一样,具体看代码

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%lld", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const ll min(const ll &a, const ll &b) { return a<b?a:b; }
    
    const int N=100005;
    int ihead[N], cnt, n;
    struct ED { int to, next; ll w; }e[N<<1];
    ll d[N][2], ans=~0ull>>1, c[N], son[N][2];
    void add(int u, int v, ll w) {
    	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].w=w;
    	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].w=w;
    }
    void dfs1(int x, int fa) {
    	int y;
    	for(int i=ihead[x]; i; i=e[i].next) if((y=e[i].to)!=fa) {
    		ll w=e[i].w;
    		dfs1(y, x);
    		son[x][0]+=son[y][0]+c[y];
    		d[x][0]+=d[y][0]+w*(son[y][0]+c[y]);
    	}
    }
    void dfs2(int x, int fa) {
    	int y;
    	for(int i=ihead[x]; i; i=e[i].next) if((y=e[i].to)!=fa) {
    		ll w=e[i].w;
    		son[y][1]=son[x][1]+c[x]+son[x][0]-son[y][0]-c[y];
    		d[y][1]=d[x][1]+w*son[y][1]+d[x][0]-d[y][0]-w*(son[y][0]+c[y]);
    		dfs2(y, x);
    	}
    }
    int main() {
    	read(n);
    	for1(i, 1, n) read(c[i]);
    	rep(i, n-1) { int u=getint(), v=getint(), w=getint(); add(u, v, w); }
    	dfs1(1, 0); dfs2(1, 0);
    	for1(i, 1, n) ans=min(ans, d[i][0]+d[i][1]);
    	print(ans);
    	return 0;
    }
    

    Description

    Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将 来参加这一次集会。当然,她会选择最方便的地点来举办这次集会。每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意一个农场都能够到达另外一个农场。道路i连接农场A_i和B_i(1 <= A_i <=N; 1 <= B_i <= N),长度为L_i(1 <= L_i <= 1,000)。集会可以在N个农场中的任意一个举行。另外,每个牛棚中居住者C_i(0 <= C_i <= 1,000)只奶牛。在选择集会的地点的时候,Bessie希望最大化方便的程度(也就是最小化不方便程度)。比如选择第X个农场作为集会地点,它的不方 便程度是其它牛棚中每只奶牛去参加集会所走的路程之和,(比如,农场i到达农场X的距离是20,那么总路程就是C_i*20)。帮助Bessie找出最方 便的地点来举行大集会。 考虑一个由五个农场组成的国家,分别由长度各异的道路连接起来。在所有农场中,3号和4号没有奶牛居住。

    Input

    第一行:一个整数N * 第二到N+1行:第i+1行有一个整数C_i * 第N+2行到2*N行,第i+N+1行为3个整数:A_i,B_i和L_i。

    Output

    * 第一行:一个值,表示最小的不方便值。

    Sample Input

    5
    1
    1
    0
    0
    2
    1 3 1
    2 3 2
    3 4 3
    4 5 3

    Sample Output

    15

    HINT

    Source

  • 相关阅读:
    iOS 应用开发入门指南
    修改Visual Studio2010的主题颜色
    C# 获取操作系统相关信息
    WPF Menu控件自定义Style
    Feedback or feedforward?
    Coprimeness
    Admissible, Stabilizability, and Bicoprime Factorization
    Directions of zeros and poles for transfer matrices
    Limit point, Accumulation point, and Condensation point of a set
    Linear System Theory: zero-input response of LTI system
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4005773.html
Copyright © 2011-2022 走看看