JZOJ5776. 【NOIP2008模拟】小x游世界树

题目:【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 }
树形DP与换根

 

posted @ 2018-08-09 19:57  杜宇一声  阅读(271)  评论(0编辑  收藏  举报