【BZOJ3677】[Apio2014]连珠线 换根DP
【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 Input
51 2 10
1 3 40
1 4 15
1 5 20
Sample Output
60HINT
數據范圍滿足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;else if(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];else fx=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;else if(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; }?
轉載于:https://www.cnblogs.com/CQzhangyu/p/7898704.html
總結
以上是生活随笔為你收集整理的【BZOJ3677】[Apio2014]连珠线 换根DP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SVN中如何去除版本控制器
- 下一篇: 联想教育应用使用说明(7.6版本)——第