题目:【NOIP2008模拟】小x游世界树;
题目的附加题解给的很清楚,这里只给一个代码;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define ms(a,x) memset(a,x,sizeof(a)) 7 #define ll long long 8 using namespace std; 9 const int MAXN=700005; 10 struct node{ 11 int y,nxt;ll z; 12 }edge[MAXN*2];int indx=0,n,head[MAXN]; 13 ll a[MAXN],ans=0x7fffffffff,rt=1,siz[MAXN],f[MAXN]; 14 void add(int x,int y,ll z){ 15 edge[++indx].y=y;edge[indx].z=z; 16 edge[indx].nxt=head[x];head[x]=indx; 17 } 18 void dp(int x,int fa){ 19 siz[x]=1; 20 for(int i=head[x],y;~i;i=edge[i].nxt){ 21 if((y=edge[i].y)==fa) continue; 22 dp(y,x);f[x]+=1LL*edge[i].z*siz[y]; 23 siz[x]+=siz[y];f[x]+=f[y]; 24 } return ; 25 } 26 void dfs(int x,int fa,ll la,ll v){ 27 la-=v*siz[x]; 28 for(int i=head[x];~i;i=edge[i].nxt){ 29 if(edge[i].y!=fa) continue; 30 la+=edge[i].z*(n-siz[x]);break; 31 } if(la<ans) ans=la,rt=x; 32 else if(la==ans) rt=min((int)x,(int)rt); 33 for(int i=head[x],y;~i;i=edge[i].nxt){ 34 if((y=edge[i].y)==fa) continue; 35 dfs(y,x,la,edge[i].z); 36 } return ; 37 } 38 int main(){ 39 // freopen("yggdrasil.in","r",stdin); 40 // freopen("yggdrasil.out","w",stdout); 41 scanf("%d",&n);ms(head,-1); 42 for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 43 for(int i=1,x,y;i<n;i++){ 44 ll z;scanf("%d%d%lld",&x,&y,&z); 45 add(x,y,a[x]>0?z-a[x]:z); 46 add(y,x,a[y]>0?z-a[y]:z); 47 } dp(1,-1);ans=min(ans,f[rt]); 48 for(int i=head[1];~i;i=edge[i].nxt) 49 dfs(edge[i].y,1,f[1],edge[i].z); 50 printf("%lld\n%lld\n",rt,ans); 51 return 0; 52 }