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
1 2
1 3 4 0
1 4 1 5
1 5 2 0
Sample Output
HINT
数据范围满足1≤n≤200000。
题解:
假如确定了根,再通过若干操作得到这棵树,那么对于insert(w,u,v)操作,u,w,v必然为祖父节点-父节点-子节点的形式
然后可以O(n)的枚举根,设 f[i][0/1] 表示以i为根的子树,i是否为中转点的情况下,子树蓝边的最大总和是多少
这个可以O(1)的从儿子转移过来,所以dp的复杂度为O(n),但总复杂度为O(n2)
我们可以在状态里多加一个0/1,即设 f[i][0/1][0/1] 表示以i为根的子树,以i的为子树里除去i以外是否有根节点,i是否为中转点的情况下,子树蓝边的最大总和是多少
当以i的为子树里除去i以外没有根节点,和前面的转移一样
否则,就会多一种转移,设根节点在j,就是可以有insert(i,j,x),其中x是i的另一个子节点
code:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char ch;
bool ok;
void read(int &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
const int maxn=;
const int maxm=maxn*;
const int inf=;
int n,a,b,c;
int f[maxn][][];
struct Graph{
int tot,now[maxn],son[maxm],pre[maxm],val[maxm];
int premax[maxn],sufmax[maxn],g[maxn];
void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
void add(int a,int b,int c){put(a,b,c),put(b,a,c);}
void dfs(int u,int fa){
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (v!=fa) dfs(v,u);
int cnt=,sum=; premax[]=sufmax[]=-inf;
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (v!=fa)
g[v]=max(f[v][][],f[v][][]+val[p]),sum+=g[v],++cnt,premax[cnt]=sufmax[cnt]=f[v][][]+val[p]-g[v];
premax[cnt+]=sufmax[cnt+]=-inf;
for (int i=;i<=cnt;i++) premax[i]=max(premax[i],premax[i-]);
for (int i=cnt;i>=;i--) sufmax[i]=max(sufmax[i],sufmax[i+]);
f[u][][]=sum,f[u][][]=cnt?f[u][][]+premax[cnt]:-inf,f[u][][]=-inf;
for (int p=now[u],v=son[p],i=;p;p=pre[p],v=son[p]) if (v!=fa){i++;
int res=max(premax[i-],sufmax[i+]),tmp=sum-g[v];
f[u][][]=max(f[u][][],max(f[v][][]+val[p]+tmp,max(f[v][][],f[v][][])+tmp+max(val[p]+res,)));
f[u][][]=max(f[u][][],max(f[v][][],f[v][][])+val[p]+tmp);
}
}
}G;
int main(){
read(n);
for (int i=;i<n;i++) read(a),read(b),read(c),G.add(a,b,c);
G.dfs(,);
printf("%d\n",max(f[][][],f[][][]));
return ;
}
bzoj3677: [Apio2014]连珠线的更多相关文章
- [Bzoj3677][Apio2014]连珠线(树形dp)
3677: [Apio2014]连珠线 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 434 Solved: 270[Submit][Status] ...
- 【BZOJ3677】[Apio2014]连珠线 换根DP
[BZOJ3677][Apio2014]连珠线 Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做“连珠线”.不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色 ...
- 【LG3647】[APIO2014]连珠线
[LG3647][APIO2014]连珠线 题面 洛谷 题解 首先考虑一下蓝线连起来的情况,一定是儿子-父亲-另一个儿子或者是儿子-父亲-父亲的父亲. 而因为一开始只有一个点在当前局面上,将一条红边变 ...
- 题解 [APIO2014]连珠线
题解 [APIO2014]连珠线 题面 解析 首先这连成的是一棵树啊. 并且\(yy\)一下,如果钦定一个根, 那么这上面的蓝线都是爸爸->儿子->孙子这样的,因为像下图这样的构造不出来: ...
- 并不对劲的bzoj3677:p3647:[APIO2014]连珠线
题目大意 有一种生成\(n\)个点的树的方法为: 一开始有一个点,\(n-1\)次操作,每次可以有两种操作:1.选一个点,用一条红边将它与新点连接:2.将新点放在一条红边上,新点与这条红边两端点直接的 ...
- APIO2014 连珠线
题目链接:戳我 换根DP 由于蒟蒻不会做这个题,所以参考了大佬. 本来想的是有三种情况,一种是该节点不作为两个蓝线的中点(我们称这种不是关键节点),一种是该节点作为关键点.连两个子节点,一种是作为关键 ...
- bzoj 3677: [Apio2014]连珠线【树形dp】
参考:http://www.cnblogs.com/mmlz/p/4456547.html 枚举根,然后做树形dp,设f[i][1]为i是蓝线中点(蓝线一定是父子孙三代),f[i][0]为不是,转移很 ...
- Luogu P3647 [APIO2014]连珠线
题目 换根dp. 显然对于给定的一棵有根树,蓝线都不能拐弯. 设\(f_{u,0}\)表示\(u\)不是蓝线中点时子树内的答案,\(f_{u,1}\)表示\(u\)是蓝线中点时子树内的答案.(以\(1 ...
- 洛谷$P3647\ [APIO2014]$连珠线 换根$dp$
正解:换根$dp$ 解题报告: 传送门! 谁能想到$9102$年了$gql$居然还没写过换根$dp$呢,,,$/kel$ 考虑固定了从哪个点开始之后,以这个点作为根,蓝线只可能是直上直下的,形如&qu ...
随机推荐
- Citrix服务器虚拟化之三十 XenApp 6.5发布流式应用程序
Citrix服务器虚拟化之三十 XenApp 6.5发布流式应用程序 XenApp可发布以下类型的资源向用户提供信息访问,这 ...
- 从 setNeedsLayout 说起
本文从 setNeedsLayout 这个方法说起,分享与其相关的 UIKit 视图交互.使用场景等内容. UIKit 为 UIView 提供了这些方法来进行视图的更新与重绘: public func ...
- Java基础知识强化之IO流笔记47:IO流练习之 随机获取文本文件中的姓名案例
1. 随机获取文本文件中的姓名案例 需求:我有一个文本文件中存储了几个名称,请大家写一个程序实现随机获取一个人的名字. 分析: A: 把文本文件中的数据存储到集 ...
- Java实现简单选择排序
package select; import java.util.Scanner; /*采用最简单的选择方式:从头到尾扫描序列找出最小的记录和第一个记录交换,接着在剩下的记录中继续这种选择和交换,最终 ...
- Java public, private, protected and default
Class Package Subclass World public y y y ...
- Oracle常用查询命令
Oracle查询完整格式如下: Select * from XX where XX group by YY having XX order by YY Select count(*), XX fr ...
- 获取当前时间日期并格式化--JS
工作当中,总是遇到很多觉得不错的JS脚本.现在觉得还是找个地方记录下来,以后可以随时查看. /** *获取当前时间日期并格式化 */ function getNowDate(){ var mydate ...
- dom+bom
一.判断最大值和最小值,注:arr为数组 最大值:Math.max.apply(null, arr); 最小值:Math.min.apply(null, arr); 二.BOM 打开新页面和关闭打 ...
- SqlServer Change Data Capture(CDC)数据变更捕获
最近在使用SqlServer2008r2数据库做系统的时候,在某些重要的.经常涉及到修改的表上,想加上一些恢复机制,一开始想找找看看有没有类似Oracle数据库闪回那样的功能,后来发现CDC的功能可以 ...
- BAT变量中的百分号学习
在BlogJava上看到如下的批处理文件,并将其转记在此: 1 2 3 4 5 6 7 8 @echo off rem bat 获取系统时间,并去掉时间小时前面的空格 rem 2012-12-12 ...