ICPC Pacific Northwest Regional Contest 2019 A题

将括号拆掉其实就是维护两个求和

任取一个作为根节点,做两次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\n",ans[i]);
}
View Code

 

posted @ 2020-05-04 18:28  朝暮不思  阅读(236)  评论(0编辑  收藏  举报