码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1827 gather 奶牛大集会

时间:2015-05-25 17:59:31      阅读:100      评论:0      收藏: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

题解:记两个数组dis[](表示根到 i 的距离), size[](表示以 i 根的树的大小),首先dfs一遍,预处理出 1 为根的树(其实可为任意点为根)的总不方便值和dis[], size[], 之后每当改变一个点做根的时候,ans(不方便值)的大小都会: - size[E[i].v] * E[i].v + (tot - size[E[i].v]) * E[i].v (tot 表示 总的牛数),也就是说只有当(2 * size[E[i].v] > tot) 时,ans才会减小。然后就没有然后了。

CODE:

#include <iostream>
#include <cstdio>
#include <cstring>
#define REP(i, s, n) for(int i = s; i <= n; i ++)
#define REP_(i, s, n) for(int i = n; i >= s; i --)
#define MAX_N 100000 + 10

using namespace std;

int n, u, v, w, pel[MAX_N];
long long dis[MAX_N], size[MAX_N];
struct node{
    int v, w, next;
}E[MAX_N << 1];
int head[MAX_N], top = 0;
long long ans = 0, tot = 0;

void add(int u, int v, int w){
    E[++ top].v = v; E[top].w = w; E[top].next = head[u]; head[u] = top;
}

void dfs1(int x,int last){
    ans += pel[x] * dis[x];
    size[x] = pel[x];
    for(int i = head[x]; i; i = E[i].next){
        if(E[i].v == last) continue;
        dis[E[i].v] = dis[x] + E[i].w;
        dfs1(E[i].v, x);
        size[x] += size[E[i].v];
    }
}

void dfs2(int x,int last){
    for(int i = head[x]; i; i = E[i].next){
        if(E[i].v == last) continue;
        if(2 * size[E[i].v] > tot){
            ans -= (2 * size[E[i].v] - tot) * E[i].w;
            dfs2(E[i].v, x);
        }
    }
}

int main(){
    scanf("%d", &n);
    REP(i, 1, n) scanf("%d", &pel[i]), tot += pel[i];
    REP(i, 1, n - 1){
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w); add(v, u, w);
    }
    dfs1(1, 0); dfs2(1, 0);
    cout << ans << endl;
    return 0;
} 

 

BZOJ 1827 gather 奶牛大集会

标签:

原文地址:http://www.cnblogs.com/ALXPCUN/p/4528083.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!