题目链接:戳我

换根DP

由于蒟蒻不会做这个题,所以参考了大佬。

本来想的是有三种情况,一种是该节点不作为两个蓝线的中点(我们称这种不是关键节点),一种是该节点作为关键点、连两个子节点,一种是作为关键节点、一个连子节点一个连父亲节点。

然后有一个不换根的树形DP,但是正确性emmm尚待商榷。

对于一个这样的图——

我们可以发现,如果想要连起来的话,我们需要不止一个根节点,而这与题目中提到的每次加入一个节点不符。

所以我们考虑换根。这样的话我们发现,就只有两种情况了——一种是该节点不作为关键节点,一种是作为关键节点、连父亲和儿子。

设\(f[i][0]\)表示对于以i为根的子树,该节点不作为关键节点的最大收益。

设\(f[i][1]\)表示对于以i为根的子树,该节点作为关键节点、连父节点和子节点的最大收益。

\(f[i][0]=max(f[i][0],f[i][1]+edge[i].dis)\)

\(f[i][1]=max(f[i][1],f[i][0]-max(dp[v][0],dp[v][1]+dis)+dis+dp[v][0])\)

之后维护一个\((f[i][0]-max(dp[v][0],dp[v][1]+dis)+dis+dp[v][0])\)的前后缀即可。

具体看代码qwqwq

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#define MAXN 200010
#define INF 0x3f3f3f3f
using namespace std;
int n,t,ans;
int head[MAXN],f[MAXN][2];
vector<int>son[MAXN],pef[MAXN],suf[MAXN],dis[MAXN];
struct Edge{int nxt,to,dis;}edge[MAXN<<1];
inline void add(int from,int to,int dis)
{
edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;
edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=dis,head[to]=t;
}
inline int dfs1(int x,int pre)
{
f[x][0]=0,f[x][1]=-INF;
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==pre) continue;
son[x].push_back(v),dis[x].push_back(edge[i].dis);
}
for(int i=0;i<son[x].size();i++)
{
int v=son[x][i],dist=dis[x][i];
dfs1(v,x);
f[x][0]+=max(f[v][0],f[v][1]+dist);
pef[x].push_back(f[v][0]-max(f[v][0],f[v][1]+dist)+dist);
suf[x].push_back(f[v][0]-max(f[v][0],f[v][1]+dist)+dist);
}
for(int i=0;i<son[x].size();i++) f[x][1]=max(f[x][1],f[x][0]+pef[x][i]);
for(int i=1;i<son[x].size();i++) pef[x][i]=max(pef[x][i],pef[x][i-1]);
for(int i=son[x].size()-2;i>=0;i--) suf[x][i]=max(suf[x][i],suf[x][i+1]);
}
inline void dfs2(int x,int f0,int f1,int dist)
{
f[x][0]+=max(f0,f1+dist);
f[x][1]+=max(f0,f1+dist);
f[x][1]=max(f[x][1],f[x][0]+f0-max(f0,f1+dist)+dist);
ans=max(ans,f[x][0]);
for(int i=0;i<son[x].size();i++)
{
int v=son[x][i];
int cur0=f[x][0]-max(f[v][0],f[v][1]+dis[x][i]);
int delta=f0-max(f0,f1+dist)+dist;
if(i!=0) delta=max(delta,pef[x][i-1]);
if(i!=son[x].size()-1) delta=max(delta,suf[x][i+1]);
dfs2(v,cur0,cur0+delta,dis[x][i]);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dfs1(1,0);
dfs2(1,0,-INF,-INF);
printf("%d\n",ans);
return 0;
}

APIO2014 连珠线的更多相关文章

  1. 【BZOJ3677】[Apio2014]连珠线 换根DP

    [BZOJ3677][Apio2014]连珠线 Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做“连珠线”.不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色 ...

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

    3677: [Apio2014]连珠线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 434  Solved: 270[Submit][Status] ...

  3. 【LG3647】[APIO2014]连珠线

    [LG3647][APIO2014]连珠线 题面 洛谷 题解 首先考虑一下蓝线连起来的情况,一定是儿子-父亲-另一个儿子或者是儿子-父亲-父亲的父亲. 而因为一开始只有一个点在当前局面上,将一条红边变 ...

  4. 题解 [APIO2014]连珠线

    题解 [APIO2014]连珠线 题面 解析 首先这连成的是一棵树啊. 并且\(yy\)一下,如果钦定一个根, 那么这上面的蓝线都是爸爸->儿子->孙子这样的,因为像下图这样的构造不出来: ...

  5. bzoj3677: [Apio2014]连珠线

    Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做“连珠线”.不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色和蓝色.游戏 开始时,只有1个珠子,而接下来新的 ...

  6. bzoj 3677: [Apio2014]连珠线【树形dp】

    参考:http://www.cnblogs.com/mmlz/p/4456547.html 枚举根,然后做树形dp,设f[i][1]为i是蓝线中点(蓝线一定是父子孙三代),f[i][0]为不是,转移很 ...

  7. Luogu P3647 [APIO2014]连珠线

    题目 换根dp. 显然对于给定的一棵有根树,蓝线都不能拐弯. 设\(f_{u,0}\)表示\(u\)不是蓝线中点时子树内的答案,\(f_{u,1}\)表示\(u\)是蓝线中点时子树内的答案.(以\(1 ...

  8. 洛谷$P3647\ [APIO2014]$连珠线 换根$dp$

    正解:换根$dp$ 解题报告: 传送门! 谁能想到$9102$年了$gql$居然还没写过换根$dp$呢,,,$/kel$ 考虑固定了从哪个点开始之后,以这个点作为根,蓝线只可能是直上直下的,形如&qu ...

  9. 洛谷 P3647 [APIO2014]连珠线(换根 dp)

    题面传送门 题意: 桌子上有 \(1\) 个珠子,你要进行 \(n-1\) 次操作,每次操作有以下两种类型: 拿出一个新珠子,并选择一个桌子上的珠子,在它们之间连一条红线 选择两个由红线相连的珠子 \ ...

随机推荐

  1. 常用sql语句备份

    1.查看数据库中所有的存储过程 use [DataBase_Name] go SELECT * FROM sys.all_objects WHERE ([type] = 'P' OR [type] = ...

  2. C#中的goto

    int i = 9;if (i % 2 == 0) goto Found;else goto NoFound; NoFound:            Console.WriteLine(i.ToSt ...

  3. Gouraud Shading

    [Gouraud Shading] Gouraud Shading (高洛德着色/高氏着色) 这种着色的效果要好得多,也是在游戏中使用最广泛的一种着色方式.它可对3D模型各顶点的颜色进行平滑.融合处理 ...

  4. Finite State Transducers

    一, 简介 Finite State Transducers 简称 FST, 中文名:有穷状态转换器.在自然语言处理等领域有很大应用,其功能类似于字典的功能(STL 中的map,C# 中的Dictio ...

  5. Sql Server 2008R2 数据库发布与订阅

    背景描述: 发布服务器A: (远程端) , 数据库服务名: GUANWANG1 订阅服务器B: (本机)   ,  数据库服务名: PC-LLRDBA 需要从服务器A中数据库发布,然后在B中订阅A发布 ...

  6. Centos7 安装Nginx服务

    第一种方式:通过yum安装 直接通过 yum install nginx 肯定是不行的,因为yum没有nginx,所以首先把 nginx 的源加入 yum 中. 运行下面的命令: 1.将nginx放到 ...

  7. Redis只作为缓存,不做持久化的配置

    #1.配置缓存内存限制和清理策略 #作为缓存服务器,如果不加以限制内存的话,就很有可能出现将整台服务器内存都耗光的情况,可以在redis的配置文件里面设置: #example: # 限定最多使用1.5 ...

  8. 关于sudo apt-get update错误 http://archive.canonical.com natty InRelease

    sudo apt-get update 错误 http://archive.canonical.com natty InRelease 错误 http://mirror.rootguide.org n ...

  9. Python手机开发调用DLL实现部分ADB功能-乾颐堂

    近期学了一点Python,然后正好有一个手机同步工具方面的预研工作要完成. 要实现PC与手机的通信,首先要找到他们的通信协议,还好的是Android有完善的协议:ADB ADB的代码是开源的,而且支持 ...

  10. [Jenkins] 全局变量

    http://www.360doc.com/content/14/1110/10/7811581_423993429.shtml https://wiki.jenkins.io/display/JEN ...