NOI2011道路修建(BZOJ2435)
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2435
2435: [Noi2011]道路修建
Time Limit: 10 Sec Memory Limit: 128 MBDescription
在 W 星球上有 n 个国家。为了各自国家的经济发展,他们决定在各个国家
之间建设双向道路使得国家之间连通。但是每个国家的国王都很吝啬,他们只愿
意修建恰好 n – 1条双向道路。 每条道路的修建都要付出一定的费用,
这个费用等于道路长度乘以道路两端的国家个数之差的绝对值。例如,在下图中,虚线所示道路两端分别有 2 个、4个国家,如果该道路长度为
1,则费用为1×|2 – 4|=2。图中圆圈里的数字表示国家的编号。
由于国家的数量十分庞大,道路的建造方案有很多种,同时每种方案的修建
费用难以用人工计算,国王们决定找人设计一个软件,对于给定的建造方案,计
算出所需要的费用。请你帮助国王们设计一个这样的软件。
Input
输入的第一行包含一个整数n,表示 W 星球上的国家的数量,国家从 1到n
编号。接下来 n – 1行描述道路建设情况,其中第 i 行包含三个整数ai、bi和ci,表
示第i 条双向道路修建在 ai与bi两个国家之间,长度为ci。
Output
输出一个整数,表示修建所有道路所需要的总费用。
Sample Input
6
1 2 1
1 3 1
1 4 2
6 3 1
5 2 1
Sample Output
20
HINT
n = 1,000,000 1≤ai, bi≤n
0 ≤ci≤ 10^6
Source
Day2
注意以一个点位根求出的子树的大小时,计算答案要用两个点的子树大小的较小值作为一边,n-min(f[a],f[b])作为另一边。NOI能考这样的水题真是不容易。。
Codes:
1 #include<set> 2 #include<queue> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 using namespace std; 10 const int N = 1000010; 11 #define For(i,n) for(int i=1;i<=n;i++) 12 #define Rep(i,l,r) for(int i=l;i<=r;i++) 13 #define Down(i,r,l) for(int i=r;i>=l;i--) 14 15 struct EDGE{ 16 int s,t,next,w; 17 }E[N<<1]; 18 19 int n,s,t,w,root,head[N],Es; 20 int f[N];long long ans; 21 22 void makelist(int s,int t,int w){ 23 E[Es].s = s; E[Es].t = t; E[Es].w = w; E[Es].next = head[s]; 24 head[s] = Es++; 25 } 26 27 int cal(int i,int fa){ 28 f[i] = 1; 29 for(int p=head[i];p!=-1;p=E[p].next){ 30 int v = E[p].t; 31 if(v!=fa) f[i]+=cal(v,i); 32 } 33 if(!f[i]) f[i] = 1; 34 return f[i]; 35 } 36 37 int read(){ 38 int num = 0;char ch = getchar(); 39 while(ch<'0'||ch>'9') ch = getchar(); 40 while('0'<=ch&&ch<='9'){ 41 num = num * 10 + ch - '0'; 42 ch = getchar(); 43 } 44 return num; 45 } 46 47 int main(){ 48 memset(head,-1,sizeof(head)); 49 n = read(); 50 For(i,n-1){ 51 s = read(); t = read(); w = read(); 52 makelist(s,t,w); 53 makelist(t,s,w); 54 f[s]++;f[t]++; 55 } 56 For(i,n) 57 if(f[i]==1){ 58 root = i; 59 break; 60 } 61 f[root] = cal(root,0); 62 for(int i=1;i<=2*n-2;i+=2){ 63 ans+=(long long)abs((n-min(f[E[i].s],f[E[i].t]))-min(f[E[i].s],f[E[i].t]))*E[i].w; 64 } 65 cout<<ans<<endl; 66 return 0; 67 }