链接:https://ac.nowcoder.com/acm/contest/3566/B
来源:牛客网
小琛是一所学校的校长。
他的学校有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条通道所需支付的费用。
4
2 1 2 3
1 3 1
1 2 3
4 1 2
24
60
56
树形dp。dfs返回子树的人数和点数。
路(a,b)的费用=(子树a的人数*子树b的点数+子树a的点数*子树b的人数)*2
#include
#include
using namespace std;
typedef long long ll;
const int N=2e5+20;
int n,a[N],head[N],cs;
ll pep,ans[N];
struct node{
int y,v,ne;
}side[N<<1];
struct Node{
ll ren,dian;
Node(){
}
Node(ll x,ll y)
{
ren=x;
dian=y;
}
};
void add(int x,int y,int v)
{
side[cs].y=y;
side[cs].v=v;
side[cs].ne=head[x];
head[x]=cs++;
return;
}
Node dfs(int x,int fa)
{
Node re=Node(a[x],1);
for(int i=head[x];i!=-1;i=side[i].ne)
{
int y=side[i].y;
int v=side[i].v;
if(y==fa)continue;
Node t=dfs(y,x);
ans[i>>1]+=(t.ren*(n-t.dian)+t.dian*(pep-t.ren))*v*2;
re.ren+=t.ren;
re.dian+=t.dian;
}
return re;
}
int main()
{
int x,y,v;
cin>>n;
pep=0;
for(int i=0;i<N;i++)
head[i]=-1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pep+=a[i];
}
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&v);
add(x,y,v);
add(y,x,v);
}
dfs(1,-1);
int en=n-1;
for(int i=0;i<en;i++)
printf("%lld\n",ans[i]);
return 0;
}