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
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 }