1. 程式人生 > >洛谷 P2986 [USACO10MAR]偉大的奶牛聚集Great Cow Gat…

洛谷 P2986 [USACO10MAR]偉大的奶牛聚集Great Cow Gat…

包括 又是 art pla tdi 思路 奶牛 最終 length

題目描述

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

@[email protected]@[email protected][2]

[1] |

2|@[1]2Bessie 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;感覺洛谷上的題解比我講的好,所以復制了一段:
   思路就是先假設所有奶牛都到一個點了,然後就可以從這個點推出所有點的狀態,O(n)的動態規劃,其實就是一維(也可以不用數組),我們記錄每個點他的所有兒子節點(包括兒子節點的節點)的奶牛總數son[i],dp[v]=dp[rt]-son[v]*a[i].w+(sum-son[v])*a[i].w;(sum是所有奶牛數總和),預處理的時候我們把所有點到第一個點的距離,接下來就可以愉快的處理出dp[1]了,然後就是一邊DFs的動態規劃並且每次比較取答案。(感謝 cheeseYang)

   

考慮如果依次枚舉每一個點作為集會的地點

使用DFS進行計算

然後再依次比較

時間復雜度O(n^2)

但是n的範圍太大,顯然會超時。

那麽,我們應當如何優化?

先看看樣例

技術分享

通過一次O(n)的計算,很容易得出來

如果選擇1號節點,答案就是17

既然O(n^2)的計算無法在時間內求解

那麽是否可以遞推出來呢?

顯然是可以的。

觀察如果已經知道1號節點所需的時間

那麽,我們可以做如下假設:

① 所有的牛首先到達了1號節點

② 3號節點以及他子樹上的節點都需要退回1->3的路徑的長度

③ 除了3號節點以及他子樹上的節點都需要前進1->3的路徑的長度

通過上面的三條東西,我們就可以從任意一個父節點推出子節點的時間

所以,又是一遍O(n)的計算就可以推出最終的答案。(感謝 yybyyb)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 using namespace std;
 6 #define man 200100
 7 #define ll long long
 8 ll n,m,a[man],ans=123456480,sum=0;
 9 ll son[man],dis[man<<1];
10 struct edge
11 {
12     ll next,to,dis;
13     }e[man];
14 ll num=0,head[man<<2];
15 ll f[man];
16 inline void add(ll from,ll to,ll dis)//添邊
17 {
18     e[++num].next=head[from];
19     e[num].to=to;
20     e[num].dis=dis;
21     head[from]=num;
22     }
23 ll dfs(ll u,ll father)//找出所有關於1節點的距離和
24 {
25     ll tot=0;
26     for(ll i=head[u];i;i=e[i].next)
27     {
28         ll to=e[i].to;
29         if(to==father)continue;
30         ll d=dfs(to,u);
31         dis[u]+=dis[to]+e[i].dis*d;
32         tot+=d;
33         }
34     return son[u]=tot+a[u];
35     }
36 void sch(ll u,ll father)//求出代價f[]
37 {
38     for(ll i=head[u];i;i=e[i].next)
39     {
40         ll to=e[i].to;
41         if(to==father)continue;
42         f[to]=f[u]-son[to]*e[i].dis+(sum-son[to])*e[i].dis;//方程
43         sch(to,u);
44         }
45     }
46 int main()
47 {
48     ios::sync_with_stdio(false);
49     cin.tie(0);
50     cin>>n;
51     for(int i=1;i<=n;i++)
52     {    cin>>a[i];sum+=a[i];}
53     for(int i=1,x,y,d;i<n;i++)
54     {
55         cin>>x>>y>>d;
56         add(x,y,d);add(y,x,d);
57         }
58     memset(f,0,sizeof(f));
59     dfs(1,1);
60     sch(1,1);
61     ans=f[1];
62     for(int i=1;i<=n;i++)
63         ans=min(ans,f[i]);
64     cout<<ans+dis[1]<<endl;
65     return 0;
66     }

註:此題不能直接在main()中直接求f[],因為此時並不知道f[1]的取值,所以仍需一次遍歷。

洛谷 P2986 [USACO10MAR]偉大的奶牛聚集Great Cow Gat…