標籤:是你 bzoj while pac set dfs 表示 tput span
【BZOJ3677】[Apio2014]連珠線Description
在列奧納多·達·芬奇時期,有一個流行的童年遊戲,叫做“連珠線”。不出所料,玩這個遊戲只需要珠子和線,珠子從1到禮編號,線分為紅色和藍色。遊戲開始時,只有1個珠子,而接下來新的珠子只能通過線由以下兩種方式被加入:
1.Append(w,杪):-個新的珠子w和一個已有的珠子杪串連,串連使用紅線。
2.Insert(w,u,v):-個新的珠子w加入到一對通過紅線串連的珠子(u,杪)之間,並將紅線改成藍線。也就是將原來u連到1的紅線變為u連到w的藍線與W連到V的藍線。
無論紅線還是藍線,每條線都有一個長度。而在遊戲的最後,將得到遊戲的最後得分:所有藍線的長度總和。
現在有一個這個遊戲的最終結構:你將擷取到所有珠子之間的串連情況和所有連線的長度,但是你並不知道每條線的顏色是什麼。
你現在需要找到這個結構下的最大得分,也就是說:你需要給每條線一個顏色f紅色或藍色),使得這種連線的色彩配置是可以通過上述提到的兩種連線方式操作得到的,並且遊戲得分最大。在本題中你只需要輸出最大的得分即可。
Input
第一行是一個正整數n,表示珠子的個數,珠子編號為1剄n。
接下來n-l行,每行三個正整數ai,bi(l≤ai10000),表示有一條長度為ci的線串連了珠子ai和珠子bi。
Output
輸出一個整數,為遊戲的最大得分。
Sample Input5
1 2 10
1 3 40
1 4 15
1 5 20Sample Output60
HINT
資料範圍滿足1≤n≤200000。
題解:一開始想了個不換根的DP,結果錯了。。。
先選擇一個點當根,那麼所有的藍線一定是 父-子-孫 這樣的。於是我們令g[x]表示當前點不是‘子‘的最大得分,f[x]表示當前點是‘子‘的最大得分,樹形DP即可。
但是我們如何換根呢?我們需要維護f的最大值和次大值,然後就能搞了。
#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn=200010;int n,cnt,ans;int to[maxn<<1],next[maxn<<1],val[maxn<<1],head[maxn],f1[maxn],g[maxn],f2[maxn];inline void add(int a,int b,int c){to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;}inline int rd(){int ret=0,f=1;char gc=getchar();while(gc<‘0‘||gc>‘9‘){if(gc==‘-‘)f=-f;gc=getchar();}while(gc>=‘0‘&&gc<=‘9‘)ret=ret*10+(gc^‘0‘),gc=getchar();return ret*f;}void dfs1(int x,int fa){f1[x]=f2[x]=-1<<30;for(int y,i=head[x];i!=-1;i=next[i])if(to[i]!=fa){y=to[i],dfs1(y,x);int fy=g[y]+val[i]-max(g[y],g[y]+f1[y]+val[i]);if(fy>f1[x])f2[x]=f1[x],f1[x]=fy;elseif(fy>f2[x])f2[x]=fy;g[x]+=max(g[y],g[y]+f1[y]+val[i]);}}void dfs2(int x,int fa){ans=max(ans,g[x]);for(int y,i=head[x];i!=-1;i=next[i])if(to[i]!=fa){y=to[i];int gx=g[x]-max(g[y],g[y]+f1[y]+val[i]),fx;if(f1[x]==g[y]+val[i]-max(g[y],g[y]+f1[y]+val[i]))fx=f2[x];elsefx=f1[x];g[y]+=max(gx,gx+fx+val[i]);fx=gx+val[i]-max(gx,gx+fx+val[i]);if(fx>f1[y])f2[y]=f1[y],f1[y]=fx;elseif(fx>f2[y])f2[y]=fx;dfs2(y,x);}}int main(){n=rd();int i,a,b,c;memset(head,-1,sizeof(head));for(i=1;i<n;i++)a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);dfs1(1,0),dfs2(1,0);printf("%d",ans);return 0;}
【BZOJ3677】[Apio2014]連珠線 換根DP