将括号拆掉其实就是维护两个求和
任取一个作为根节点,做两次dfs
考虑使用贡献来更新答案
而第二次dfs考虑这条边权的影响
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+10; const int mod=11092019; ll t[N]; int n,m; ll ans[N]; ll v[N],depth[N]; ll f1[N],f2[N]; int h[N],ne[N],e[N],idx; ll w[N]; ll sum; void add(int a,int b,ll c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } void dfs1(int u,int fa){ int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; dfs1(j,u); depth[u]+=depth[j]; v[u]+=v[j]; f1[u]+=1ll*w[i]*depth[j]+f1[j]; f2[u]+=1ll*w[i]*v[j]+f2[j]; } depth[u]++; v[u]+=t[u]; } void dfs2(int u,int fa){ ans[u]=t[u]*f1[u]+f2[u]; int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; f1[j]=f1[u]+1ll*w[i]*(n-depth[j])-w[i]*depth[j]; f2[j]=f2[u]+1ll*w[i]*(sum-v[j])-w[i]*v[j]; dfs2(j,u); } } int main(){ cin>>n; int i; memset(h,-1,sizeof h); for(i=1;i<=n;i++){ scanf("%lld",&t[i]); sum+=t[i]; } for(i=1;i<n;i++){ int a,b; ll c; scanf("%d%d%lld",&a,&b,&c); add(a,b,c); add(b,a,c); } dfs1(1,-1); dfs2(1,-1); for(i=1;i<=n;i++) printf("%lld ",ans[i]); }