1. 程式人生 > >[NOI2011]道路修建

[NOI2011]道路修建

ring [1] pla spa play cdn 建設 range com

題目描述

在 W 星球上有 n 個國家。為了各自國家的經濟發展,他們決定在各個國家 之間建設雙向道路使得國家之間連通。但是每個國家的國王都很吝嗇,他們只願 意修建恰好 n – 1 條雙向道路。 每條道路的修建都要付出一定的費用,這個費用等於道路長度乘以道路兩端 的國家個數之差的絕對值。例如,在下圖中,虛線所示道路兩端分別有 2 個、4 個國家,如果該道路長度為 1,則費用為 1×|2 – 4|=2。圖中圓圈裏的數字表示國 家的編號。 技術分享圖片

由於國家的數量十分龐大,道路的建造方案有很多種,同時每種方案的修建 費用難以用人工計算,國王們決定找人設計一個軟件,對於給定的建造方案,計 算出所需要的費用。請你幫助國王們設計一個這樣的軟件。

輸入輸出格式

輸入格式:

輸入的第一行包含一個整數 n,表示 W 星球上的國家的數量,國家從 1 到 n 編號。 接下來 n – 1 行描述道路建設情況,其中第 i 行包含三個整數 ai、bi和 ci,表 示第 i 條雙向道路修建在 ai與 bi兩個國家之間,長度為 ci。

輸出格式:

輸出一個整數,表示修建所有道路所需要的總費用。

輸入輸出樣例

輸入樣例#1:
6
1 2 1
1 3 1
1 4 2
6 3 1
5 2 1
輸出樣例#1:
20

說明

1≤ai, bi≤n

0≤ci≤10^6

2≤n≤10^6

技術分享圖片

解題思路:

很明顯這是一棵樹,可以預處理處每個節點的size(大小)

那麽就可以枚舉每條邊,邊(u,v) dep[u]<dep[v]

對於這條邊來說,兩邊的點的個數分別為

size[v] 和 size[1]-size[v]

註意LL問題

技術分享圖片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define ll long long
 6 #include<cstring>
 7 #include<string>
 8 #define DB double
 9
using namespace std; 10 const int N=2000010; 11 struct node{ 12 int u,v,c,ne; 13 }e[N]; 14 int h[N],tot,n; 15 void add(int u,int v,int c) 16 { 17 tot++;e[tot]=(node){u,v,c,h[u]};h[u]=tot; 18 } 19 int dep[N],f[N],size[N]; 20 void dfs(int u) 21 { 22 size[u]=1; 23 for(int i=h[u];i;i=e[i].ne) 24 { 25 int rr=e[i].v; 26 if(dep[rr]==0) 27 { 28 dep[rr]=dep[u]+1;f[rr]=u; 29 dfs(rr); 30 size[u]+=size[rr]; 31 } 32 } 33 } 34 ll ans; 35 int main() 36 { 37 scanf("%d",&n); 38 for(int i=1,x,y,z;i<=n-1;++i) 39 { 40 scanf("%d%d%d",&x,&y,&z); 41 add(x,y,z);add(y,x,z); 42 } 43 dep[1]=1; 44 dfs(1); 45 for(int i=1;i<=tot;i+=2) 46 { 47 int u=e[i].u,v=e[i].v; 48 if(dep[u]>dep[v]) swap(u,v); 49 int l=size[v],r=(size[1]-size[v]); 50 ans+=(ll)e[i].c*abs(l-r); 51 } 52 printf("%lld",ans); 53 return 0; 54 }
View Code

勢力分華,不近者為潔,近之而不染者尤潔。

[NOI2011]道路修建