小琛和他的学校

题目描述
小琛是一所学校的校长。
他的学校有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;
}
发布了416 篇原创文章 · 获赞 228 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/103745226
今日推荐