码迷,mamicode.com
首页 > Windows程序 > 详细

bzoj3677【APIO2014】连珠线

时间:2016-04-29 20:01:54      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:

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;
}


bzoj3677【APIO2014】连珠线

标签:

原文地址:http://blog.csdn.net/aarongzk/article/details/51224225

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!