题目描述
小琛是一所学校的校长。
他的学校有n个校区(编号1~n),被n-1条双向道路连接,呈树形结构。
第i个校区共有Ai个学生。
第i天早上,所有的学生会沿最短路走到第i个校区参加活动,晚上再原路返回。
一个人通过第j条通道一次(即一人次),需要小琛支付wj的维护费用。
小琛想知道第n天结束之后,对于每一条通道,他总共需要支付多少费用。
对于100%的数据,1≤ n ≤ 200,000,1≤ A[i]≤ 10,000,1≤ w[i] ≤ 10,000。
输入描述:
第一行一个整数n,表示校区的数量。
接下来一行,n个整数,表示A1~An。
第3到第n+1行,每行包含3个整数。第i行包含三个整数ui-2,vi-2,wi-2,表示第i-2条通道所连接的两个校区的编号,以及一人次通过这条通道的费用。
输出描述:
共n-1行,每行一个整数。
第i行的整数表示小琛对于第i条通道所需支付的费用。
示例1
输入
复制
4
2 1 2 3
1 3 1
1 2 3
4 1 2
输出
复制
24
60
56
树上dp一下,维护一下子树的size和加上人数的size即可。
然后有来回,所以再乘以2.
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n,a[N],sz[N],sum,psz[N],res[N];
int head[N],nex[N<<1],to[N<<1],w[N<<1],id[N<<1],tot;
inline void ade(int a,int b,int c,int d){
to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot; id[tot]=d;
}
inline void add(int a,int b,int c,int d){ade(a,b,c,d); ade(b,a,c,d);}
void dfs(int x,int fa){
sz[x]=1; psz[x]=a[x];
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa) continue;
dfs(to[i],x);
sz[x]+=sz[to[i]]; psz[x]+=psz[to[i]];
res[id[i]]=w[i]*2*((sum-psz[to[i]])*sz[to[i]]+psz[to[i]]*(n-sz[to[i]]));
}
}
signed main(){
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
for(int i=1,a,b,c;i<n;i++) cin>>a>>b>>c,add(a,b,c,i);
dfs(1,0);
for(int i=1;i<n;i++) cout<<res[i]<<'\n';
return 0;
}