luogu 2986

来源:互联网 发布:ubuntu修改文件夹权限 编辑:程序博客网 时间:2024/06/01 15:56

P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat…

题目描述

Bessie is planning the annual Great Cow Gathering for cows all across the country and, of course, she would like to choose the most convenient location for the gathering to take place.
Each cow lives in one of N (1 <= N <= 100,000) different barns (conveniently numbered 1..N) which are connected by N-1 roads in such a way that it is possible to get from any barn to any other barn via the roads. Road i connects barns A_i and B_i (1 <= A_i <= N; 1 <= B_i <= N) and has length L_i (1 <= L_i <= 1,000). The Great Cow Gathering can be held at any one of these N barns. Moreover, barn i has C_i (0 <= C_i <= 1,000) cows living in it.
When choosing the barn in which to hold the Cow Gathering, Bessie wishes to maximize the convenience (which is to say minimize the inconvenience) of the chosen location. The inconvenience of choosing barn X for the gathering is the sum of the distances all of the cows need to travel to reach barn X (i.e., if the distance from barn i to barn X is 20, then the travel distance is C_i*20). Help Bessie choose the most convenient location for the Great Cow Gathering.
Consider a country with five barns with [various capacities] connected by various roads of varying lengths. In this set of barns, neither barn 3 nor barn 4 houses any cows.
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找出最方便的地点来举行大集会。

输入输出格式

输入格式:

第一行:一个整数 N 。

第二到 N+1 行:第 i+1 行有一个整数 C_i

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

输出格式:
第一行:一个值,表示最小的不方便值。

输入输出样例

输入样例#1:
5
1
1
0
0
2
1 3 1
2 3 2
3 4 3
4 5 3

输出样例#1:
15

思路

第一遍dfs记录出以1为根时往下遍历时记录出这个点的子节点数fn[]和以这个节点为根时的最小不方便值fv[],设f[]为以这个节点为整颗树的根时的最小不方便值,我们思考以这个节点为整颗树的根时,状态和什么有关系,易知与这个点的父节点的f[]减去他到他父节点的不方便值,和除了这点的子节点到他的距离,同时可知距离可通过父节点求出,得出dp方程

fi=fa(fnifahi)+(totfni)fahi

(第一道自己找出方程的树形dp)

//第一遍dfs时要记录这个节点有多少子节点和值#include <cstdio>#include <algorithm>#include <cstring>#define MAXN 1000010using namespace std;long long fn[MAXN], fv[MAXN], fa[MAXN], fah[MAXN], f[MAXN]; // 表示以i为根的最小不方便值long long n, cnt, x, y, z, tot, c[MAXN], now[MAXN], ans;bool vis[MAXN];struct E {    long long from, to, nxt, vl;}es[MAXN];void addedge(long long a, long long b, long long c) {    es[++cnt].from = a;    es[cnt].to = b;    es[cnt].nxt = now[a];    now[a] = cnt;    es[cnt].vl = c;}long long read() {    int f = 1, k = 0;    char c = getchar();    while(c < '0' || c > '9') {        if(c == '-') {            f = -1;        }        c = getchar();    }    while(c >= '0' && c <= '9') {        k = k * 10 + c - '0';        c = getchar();    }    return f * k;}void dfs(int a) {    vis[a] = 1;    for(int i = now[a]; i != 0; i = es[i].nxt) {        if(!vis[es[i].to]) {            fa[es[i].to] = a;            fah[es[i].to] = es[i].vl;            dfs(es[i].to);            fn[a] += fn[es[i].to];            fv[a] += (fn[es[i].to] * es[i].vl);            fv[a] += fv[es[i].to];        }    }}void dp(int a) {    vis[a] = 1;    for(int i = now[a]; i != 0; i = es[i].nxt) {        if(!vis[es[i].to]) {            f[es[i].to] = f[a] - (fn[es[i].to] * fah[es[i].to]) + (tot - fn[es[i].to]) * fah[es[i].to];            ans = min(f[es[i].to], ans);            dp(es[i].to);        }    }}int main() {    n = read();    for(int i = 1; i <= n; i ++) {        c[i] = read();        fn[i] = c[i];        tot += c[i];    }    for(int i = 1; i < n; i ++) {        x = read(), y = read(), z = read();        addedge(x, y, z);        addedge(y, x, z);    }    dfs(1);    ans = fv[1];    f[1] = fv[1];    memset(vis, 0, sizeof(vis));    dp(1);    printf("%lld", ans);    return 0;}