1. 程式人生 > >洛谷 P2986 [USACO10MAR]Great Cow Gat…(樹形dp+容斥原理)

洛谷 P2986 [USACO10MAR]Great Cow Gat…(樹形dp+容斥原理)

nco more printf ide eva gre ans names get

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.

1 3 4 5

@--1--@--3--@--3--@[2]

[1] |

2 | @[1] 2 Bessie can hold the Gathering in any of five barns; here is the table of inconveniences calculated for each possible location:

Gather ----- Inconvenience ------

Location B1 B2 B3 B4 B5 Total

1 0 3 0 0 14 17

2 3 0 0 0 16 19

3 1 2 0 0 12 15

4 4 5 0 0 6 15

5 7 8 0 0 0 15

If Bessie holds the gathering in barn 1, then the inconveniences from each barn are:

Barn 1 0 -- no travel time there!

Barn 2 3 -- total travel distance is 2+1=3 x 1 cow = 3 Barn 3 0 -- no cows there!

Barn 4 0 -- no cows there!

Barn 5 14 -- total travel distance is 3+3+1=7 x 2 cows = 14 So the total inconvenience is 17.

The best possible convenience is 15, achievable at by holding the Gathering at barns 3, 4, or 5.

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找出最方便的地點來舉行大集會。

輸入輸出格式

輸入格式:

  • Line 1: A single integer: N

  • Lines 2..N+1: Line i+1 contains a single integer: C_i

  • Lines N+2..2*N: Line i+N+1 contains three integers: A_i, B_i, and L_i

輸出格式:

  • Line 1: The minimum inconvenience possible

輸入輸出樣例

輸入樣例#1:
5 
1 
1 
0 
0 
2 
1 3 1 
2 3 2 
3 4 3 
4 5 3 
輸出樣例#1:
15 

/*
樹形dp+容斥原理
f[i]表示i為關鍵點答案
dis[i]表示以i為根子樹和,第一遍樹形dp統計 
num[i]表示點權和,tot為總點權和 
容斥原理: f[v]=f[now]+(tot-num[v])*e[i].d-num[v]*e[i].d; 第二遍樹形dp統計 
由父親節點轉移到兒子節點 容斥比較難想一些,建議畫圖比照代碼理解
一定明確要求Σ點權*邊權最小,容斥的時候註意計算的是那個點的點權*哪條邊的邊權 
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 100007

using namespace std;
int head[N],w[N];
long long f[N],num[N],dis[N],tot;
int n,m,x,y,z,cnt;
struct edge
{
    int u,to,pre,d;
}e[N<<1];

inline void add(int u,int to,int d)
{
    e[++cnt].to=to;e[cnt].d=d;e[cnt].pre=head[u];head[u]=cnt;
}

void tree_dp1(int fa,int now)
{
    num[now]=w[now];
    for(int i=head[now];i;i=e[i].pre)
    {
        if(e[i].to==fa) continue;
        tree_dp1(now,e[i].to);
        num[now]+=num[e[i].to];
        dis[now]+=dis[e[i].to]+num[e[i].to]*e[i].d;
    }
}

long long mn=999999999999999LL;

void tree_dp2(int fa,int now)
{
    mn=min(mn,f[now]);
    for(int i=head[now];i;i=e[i].pre)
    {
        int v=e[i].to;
        if(v==fa) continue;
        f[v]=f[now]+(tot-num[v])*e[i].d-num[v]*e[i].d;
        tree_dp2(now,v);
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
      scanf("%d",&w[i]),tot+=w[i];
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    tree_dp1(0,1);
    f[1]=dis[1];
    tree_dp2(0,1);
    printf("%lld\n",mn);
    return 0;
}

洛谷 P2986 [USACO10MAR]Great Cow Gat…(樹形dp+容斥原理)