bzoj3677【APIO2014】连珠线

3677: [Apio2014]连珠线

Time Limit: 10 Sec  Memory Limit: 128 MB

Submit: 204  Solved: 115

[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

1 3 4 0

1 4 1 5

1 5 2 0

Sample Output

60

HINT

数据范围满足1≤n≤200000。

树形DP思路好题

假设初始节点为根,则蓝线链接的点一定是父亲-儿子-孙子关系。

先DP一次,然后再DFS,同时O(1)换根转移。

具体方法:

http://www.cnblogs.com/mmlz/p/4456547.html

http://blog.csdn.net/regina8023/article/details/45664389

DP信息在O(1)时间内转移,从而枚举到每一种情况的思路很好。

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define ull unsigned long long
#define maxn 200005
#define inf 2000000005
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int n,ans,cnt,head[maxn],f[maxn];
struct edge_type{int next,to,v;}e[maxn*2];
struct data{int k,v;}d[maxn][2];
inline void add_edge(int x,int y,int v)
{
	e[++cnt]=(edge_type){head[x],y,v};head[x]=cnt;
	e[++cnt]=(edge_type){head[y],x,v};head[y]=cnt;
}
inline void update(int x,int num,int v)
{
	if (v>=d[x][0].v) d[x][1]=d[x][0],d[x][0]=(data){num,v};
	else if (v>d[x][1].v) d[x][1]=(data){num,v};
}
inline void dp(int x,int fa)
{
	d[x][0].v=d[x][1].v=-inf;
	f[x]=0;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (y==fa) continue;
		dp(y,x);
		int tmp=max(f[y],f[y]+d[y][0].v+e[i].v);
		f[x]+=tmp;
		update(x,y,f[y]+e[i].v-tmp);
	}
}
inline void dfs(int x,int fa)
{
	ans=max(ans,f[x]);
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (y==fa) continue;
		int ff=f[y];data dd0=d[y][0],dd1=d[y][1];
		int tmp=max(f[y],f[y]+d[y][0].v+e[i].v);
		int newfx=f[x]-tmp;
		int newk=d[x][0].k==y?1:0;
		int newtmp=max(newfx,f[x]+d[x][newk].v-tmp+e[i].v);
		f[y]+=newtmp;
		update(y,x,newfx+e[i].v-newtmp);
		dfs(y,x);
		f[y]=ff;d[y][0]=dd0;d[y][1]=dd1;
	}
}
int main()
{
	n=read();
	F(i,1,n-1)
	{
		int x=read(),y=read(),v=read();
		add_edge(x,y,v);
	}
	ans=-inf;
	dp(1,0);
	dfs(1,0);
	printf("%d\n",ans);
	return 0;
}
时间: 2024-12-18 11:00:38

bzoj3677【APIO2014】连珠线的相关文章

[Bzoj3677][Apio2014]连珠线(树形dp)

3677: [Apio2014]连珠线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 434  Solved: 270[Submit][Status][Discuss] Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做“连珠线”.不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色和蓝色.游戏 开始时,只有1个珠子,而接下来新的珠子只能通过线由以下两种方式被加入: 1.Append(w,杪):-个新的珠子w

[BZOJ3677][Apio2014]连珠线

试题描述 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做"连珠线".不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色和蓝色.游戏开始时,只有1个珠子,而接下来新的珠子只能通过线由以下两种方式被加入:1.Append(w,v):一个新的珠子w和一个已有的珠子v连接,连接使用红线. 2.Insert(w,u,v):一个新的珠子w加入到一对通过红线连接的珠子(u,v)之间,并将红线改成蓝线.也就是将原来u连到1的红线变为u连到w的蓝线与W连到V的蓝线. 无论红线还是蓝线

【BZOJ 3677】 [Apio2014]连珠线

3677: [Apio2014]连珠线 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 119 Solved: 60 [Submit][Status][Discuss] Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做"连珠线".不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色和蓝色.游戏 开始时,只有1个珠子,而接下来新的珠子只能通过线由以下两种方式被加入: 1.Append(w,杪):-个新

APIO2014 连珠线

题目链接:戳我 换根DP 由于蒟蒻不会做这个题,所以参考了大佬. 本来想的是有三种情况,一种是该节点不作为两个蓝线的中点(我们称这种不是关键节点),一种是该节点作为关键点.连两个子节点,一种是作为关键节点.一个连子节点一个连父亲节点. 然后有一个不换根的树形DP,但是正确性emmm尚待商榷. 对于一个这样的图-- 我们可以发现,如果想要连起来的话,我们需要不止一个根节点,而这与题目中提到的每次加入一个节点不符. 所以我们考虑换根.这样的话我们发现,就只有两种情况了--一种是该节点不作为关键节点,

Luogu P3647 [APIO2014]连珠线

题目 换根dp. 显然对于给定的一棵有根树,蓝线都不能拐弯. 设\(f_{u,0}\)表示\(u\)不是蓝线中点时子树内的答案,\(f_{u,1}\)表示\(u\)是蓝线中点时子树内的答案.(以\(1\)为根的情况下) 那么显然有\(f_{u,0}=\sum\limits_{v\in son_u}\max(f_{v,0},f_{v,1}+d_v)\). (\(son_u\)表示\(u\)的儿子集合,\(d_u\)表示\((u,fa_u)\)的长度) 但是\(f_{u,1}\)如何求? 我们这样考

动态规划小练

终于意识到动规的水平差得一批了.这边开个小专题练一下. 题目列表是学长 frank_c1 的博客.这样一来可以保证质量,二来也有自己能看懂的题解. 事实上很多题意也是贺的 这里还是挂个链接吧:orz (刷新以获取数学公式) [APIO 2014] Beads and wires 题意 在达芬奇时代,有一个流行的儿童游戏称为连珠线.当然,这个游戏是关于珠子和线的.线是红色或蓝色的,珠子被编号为 $ 1 $ 到 $ n $ .这个游戏从一个珠子开始,每次会用如下方式添加一个新的珠子: $ Appen

基于HTML5实现五彩连珠小游戏

今天给大家分享一款基于HTML5实现五彩连珠小游戏.这款游戏的规则:点击彩球移动到期望的位置,每移动一次,画面将随机出现3个新的彩球:当同一颜色的彩球连成5个一行或一列或一斜线时,这5个彩球同时消失,游戏得分10分.当画面上每个方格都被彩球占满时,游戏结束. 在线预览   源码下载 实现的代码. html代码: <canvas id="canvas" height="400" width="600" style="backgrou

线扫相机项目中定量判断机构运动是否匀速的方法

线扫相机的原理:线扫相机一般一次只拍摄一条线(线宽通常是1个像素),在机构运动的过程中,线扫相机不断地拍摄线,于是“聚线成面”,这就是线扫相机成像的原理. 线扫相机的原理决定了,它所拍摄的物体必须要运动.机构运动的话,就存在机构的速度是否和线扫相机采集的速度匹配的问题. 将对机构运动速度的要求进行拆分的话,其实就是如下两点: ① 运动速度必须与线扫相机的工作行频(即采集速度)相匹配. ② 机构的运动速度最好是匀速,或者十分接近匀速. 如果机构速度过快,最后的图像在运动方向上被压缩:如果机构速度过

半截水晶头线接激活本地虚拟网卡

可有可无的小方法~ 很多人在用虚拟机的时候,有时虚拟网卡不够用,又没有可用网线插来激活本地网卡时,这时可以自制一个水晶头加半截网线(或者从水晶头还 能用的废掉的网线上截取下来如下图)来激活本地网卡,多增加一个可用虚拟网卡(虽然第一次在当时无法解决(^-^)) 制作方法:截取或制作成水晶头后,将线皮剥掉至漏出铜线,将线序颜色排列成T-568B的线序(如下图) 以10/100兆太网网卡为例的DTE类型接口引脚定义为(对应上图从左到右): 1-TX+Tranceive  Data+  (发信号+)