Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 163840/163840 K (Java/Others)
Total Submission(s): 1149 Accepted Submission(s): 457
php
//作法很好想但實現很難,兩條邊以上的路徑有兩種,一種是兒子節點及其後代和父親鏈接的路徑 //另外一種是兄弟之間鏈接的路徑但處理兄弟之間組成的路徑很差處理。dp[i]存i節點以及其後代的 //權值和,cntp[i]存i節點以及其後代中共有多少個節點。好難。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int n,head[300009],tol,pa[300009],cntp[300009],val[300009],S[300009]; ll dp[300009],vc[300009],vw[300009],ans; struct node{ int v,w,next; }nodes[600009]; void Add(int x,int y,int z){ nodes[tol].v=y; nodes[tol].w=z; nodes[tol].next=head[x]; head[x]=tol++; } void dfs(int u,int fa){ cntp[u]=1;dp[u]=val[u]; ll sum=0; for(int i=head[u];i!=-1;i=nodes[i].next){ int v=nodes[i].v; if(v==fa) continue; pa[v]=nodes[i].w; dfs(v,u); } int c=0; for(int i=head[u];i!=-1;i=nodes[i].next){ int v=nodes[i].v; if(v==fa) continue; cntp[u]+=cntp[v]; if(!vc[nodes[i].w]) S[++c]=nodes[i].w; vc[nodes[i].w]+=cntp[v]; vw[nodes[i].w]+=dp[v]; if(nodes[i].w!=pa[u])//更新u dp[u]+=dp[v]+1ll*cntp[v]*val[u]; ans+=dp[v]+1ll*cntp[v]*val[u];//和父親鏈接 sum+=dp[v]; ans+=((sum-vw[nodes[i].w])*cntp[v]+dp[v]*(cntp[u]-1-vc[nodes[i].w])+1ll*val[u]*cntp[v]*(cntp[u]-1-vc[nodes[i].w]));//兄弟之間鏈接 } cntp[u]-=vc[pa[u]];//減去顏色衝突的 while(c){ vc[S[c]]=0; vw[S[c--]]=0; } } int main() { while(scanf("%d",&n)==1){ int x,y,z; tol=0; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&z); Add(x,y,z); Add(y,x,z); } ans=0;pa[1]=0; dfs(1,0); printf("%I64d\n",ans); } return 0; }