[Bzoj3677][Apio2014]连珠线(树形dp)
2018-04-12 17:18
253 查看
3677: [Apio2014]连珠线
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 434 Solved: 270
[Submit][Status][Discuss]
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
5 1 2 10 1 3 40 1 4 15 1 5 20
Sample Output
60
HINT
数据范围满足1≤n≤200000。
分析:
一开始以为定义状态f[i][0/1]表示第i个点是不是中心点乱树形dp就可以了,结果考完只有10分原因:这个题加入有顺序,任何时刻加入的点都是一个联通块。 这样我们就要枚举根节点,并且合并只能合并 父-子-孙。 然后复杂度是O(n^2)的。 我们可以优化一下换根,不用每次换根都去枚举,如果每次只枚举当前根节点没当过根的儿子,会重新dp的只有两个点,换根复杂度O(1) 所以总复杂度O(n) 然后一开始用了vector啥的,bzoj上过了,cena上一首凉凉送给stl,被迫看了别人的代码改出来QAQ
AC代码:
# include <iostream> # include <cstdio> using namespace std; const int N = 3e5 + 12; const int inf = 0x3f3f3f3f; int head ,dt,n,ans,f1 ,f2 ,g ; struct Edge{ int to,nex,w; }edge[N << 1]; void AddEdge(int u,int v,int w) { edge[++dt] = (Edge){v,head[u],w}; head[u] = dt; } void dfs(int u,int pre) { f1[u] = f2[u] = -inf;int t; for(int i = head[u];i;i = edge[i].nex) { if(edge[i].to == pre)continue; dfs(edge[i].to,u); t = g[edge[i].to] + edge[i].w - max(g[edge[i].to],g[edge[i].to] + f1[edge[i].to] + edge[i].w); if(t > f1[u])f2[u] = f1[u],f1[u] = t; else if(t > f2[u])f2[u] = t; g[u] += max(g[edge[i].to],g[edge[i].to] + f1[edge[i].to] + edge[i].w); } } void Dfs(int u,int pre) { ans = max(ans,g[u]);int s,t,c; for(int i = head[u];i;i = edge[i].nex) { if(edge[i].to == pre)continue; s = g[u] - max(g[edge[i].to],g[edge[i].to] + f1[edge[i].to] + edge[i].w); t = g[edge[i].to] + edge[i].w - max(g[edge[i].to],g[edge[i].to] + f1[edge[i].to] + edge[i].w); if(f1[u] == t)c = f2[u];else c = f1[u]; g[edge[i].to] += max(s,s + c + edge[i].w); t = s + edge[i].w - max(s,s + c + edge[i].w); if(t > f1[edge[i].to])f2[edge[i].to] = f1[edge[i].to],f1[edge[i].to] = t; else if(t > f2[edge[i].to])f2[edge[i].to] = t; Dfs(edge[i].to,u); } } int main() { freopen("beads.in","r",stdin); freopen("beads.out","w",stdout); scanf("%d",&n);int x,y,z; for(int i = 1;i < n;i++) { scanf("%d %d %d",&x,&y,&z); AddEdge(x,y,z);AddEdge(y,x,z); } dfs(1,-1);Dfs(1,-1); printf("%d\n",ans); fclose(stdin); fclose(stdout); return 0; }
相关文章推荐
- [bzoj3677][Apio2014]连珠线【树形dp】
- BZOJ 3677【Apio2014】连珠线 树形dp
- bzoj 3677: [Apio2014]连珠线【树形dp】
- 【BZOJ3677】[Apio2014]连珠线 换根DP
- 【BZOJ 3677】 [Apio2014]连珠线
- 【bzoj3675】[Apio2014]序列分割 斜率优化dp
- BZOJ3572 [Hnoi2014]世界树 【虚树 + 树形dp】
- [BZOJ 3675][APIO 2014]序列分割(斜率优化DP)
- BZOJ_3573_[Hnoi2014]米特运输_树形DP+hash
- [ BZOJ3572 ] [ Hnoi2014 ] [ 虚树 ] [ 树形DP ] 世界树
- BZOJ3675 [Apio2014]序列分割 【斜率优化dp】
- [BZOJ3675][Apio2014]序列分割(斜率优化dp)
- bzoj-3675 序列分割APIO2014 斜率优化dp
- BZOJ 3727 PA2014 Final Zadanie 树形DP
- BZOJ 3677 & UOJ 105 [APIO2014]Beads and wires
- BZOJ3675 [Apio2014]序列分割 【斜率优化dp】
- BZOJ 3566: [SHOI2014]概率充电器( 树形dp )
- bzoj3675: [Apio2014]序列分割【斜率优化dp】
- [BZOJ 3675][Apio2014]序列分割:DP斜率优化
- bzoj 3611: [Heoi2014]大工程 (虚树+树形DP)