1. 程式人生 > >JZOJ5776. 【NOIP2008模擬】小x遊世界樹

JZOJ5776. 【NOIP2008模擬】小x遊世界樹

ref alt zoj style return ++i col oid void

題目:【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與換根

JZOJ5776. 【NOIP2008模擬】小x遊世界樹