BZOJ2435:[NOI2011]道路修建 (差分)

Description

在 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

Solution

前缀和一下,然后枚举边计算答案即可。

哦对了这个题容易爆栈……Dfs的时候我少开了long long然后就过了(一开始所有都是long long)

Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #define MAX (1000000+10)
 6 using namespace std;
 7 
 8 struct node{int next,to,len;}edge[MAX*2];
 9 int Father[MAX],Sum[MAX];
10 int head[MAX],num_edge,n;
11 long long ans;
12 
13 void add(int u,int v,int l)
14 {
15     edge[++num_edge].to=v;
16     edge[num_edge].next=head[u];
17     edge[num_edge].len=l;
18     head[u]=num_edge;
19 }
20 
21 void Build(int x)
22 {
23     Sum[x]=1;
24     for (int i=head[x];i;i=edge[i].next)
25         if (edge[i].to!=Father[x])
26         {
27             Father[edge[i].to]=x;
28             Build(edge[i].to);
29             Sum[x]+=Sum[edge[i].to];
30         }
31 }
32 
33 void Dfs(int x)
34 {
35     for (int i=head[x];i;i=edge[i].next)
36         if (edge[i].to!=Father[x])
37         {
38             ans+=(long long)edge[i].len*abs(n-(Sum[edge[i].to]<<1));
39             Dfs(edge[i].to);
40         }
41 }
42 
43 int main()
44 {
45     int u,v,l;
46     scanf("%d",&n);
47     for (int i=1;i<=n-1;++i)
48     {
49         scanf("%d%d%d",&u,&v,&l);
50         add(u,v,l); add(v,u,l);
51     }
52     Build(1);
53     Dfs(1);
54     printf("%lld",ans);
55 }
原文地址:https://www.cnblogs.com/refun/p/8678606.html