题目

换根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}\)如何求?

我们这样考虑:穿过\(u\)的蓝线就一条,我们枚举这条蓝线到它的哪个儿子,这个儿子的单独算,其它的儿子的答案则和上面一样(这一部分可以直接蒯下来而不必另算)。

\(f_{u,1}=f_{u,0}+\max\limits_{v\in son_u}(f_{v,0}+d_v-\max(f_{v,0},f_{v,1}+d_v))\)。

然后我们可以\(O(n^2)\)做了对吧。

再设\(g_{u,0,v}\)表示和上面一样的意义,并且不考虑\(u\)的孩子\(v\)情况下的答案。

显然有\(g_{u,0,v}=f_{u,0}-\max(f_{v,0},f_{v,1}+d_v)\)。

\(g_{u,1,t}=g_{u,0,t}+\max\limits_{v\in son_u\wedge v\neq t}(f_{v,0}+d_v-\max(f_{v,0},f_{v,1}+d_v))\)。

这个我们可以在每次计算\(f_{u,1}\)时处理出\((f_{v,0}+d_v-\max(f_{v,0},f_{v,1}+d_v))\)的最大值和次大值来计算。

然后开始换根。

还是dfs,对于\(u\)以及\(v\in son_u\),我们这样计算:

把\(g_{u,?,v}\)赋给\(f_{u,?}\),然后把父亲的\(f\)以及\(d_u\)合并到\(u\)来,再统计答案。

这样我们可以保证在\((1,u)\)这条链上,每个点都只计算了这条链以外儿子的子树的答案以及连接它自己和它的父亲的答案,即\(u\)的\(v\)以外子树的答案。

具体的看看代码能够很轻松地理解。

#include<bits/stdc++.h>
#define pi pair<int,int>
#define pb push_back
using namespace std;
const int N=200003,inf=1e9;
vector<pi>E[N];int f[N][2],fa[N],d[N],ans;vector<int>son[N],g[N][2],mx[N];
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
int max(int a,int b){return a>b? a:b;}
int min(int a,int b){return a<b? a:b;}
void dfs(int u)
{
int mx1=-inf,mx2=-inf,x;
for(auto [v,w]:E[u])
{
if(v==fa[u]) continue;
d[v]=w,fa[v]=u,son[u].pb(v),dfs(v),f[u][0]+=max(f[v][0],f[v][1]+w),x=f[v][0]+w-max(f[v][0],f[v][1]+w);
if(x>mx1) mx2=mx1,mx1=x; else if(x>mx2) mx2=x;
}
f[u][1]=f[u][0]+mx1;
for(auto [v,w]:E[u])
{
if(v==fa[u]) continue;
g[u][0].pb(f[u][0]-max(f[v][0],f[v][1]+w)),x=f[v][0]+w-max(f[v][0],f[v][1]+w);
x==mx1? (g[u][1].pb(g[u][0].back()+mx2),mx[u].pb(mx2)):(g[u][1].pb(g[u][0].back()+mx1),mx[u].pb(mx1));
}
}
void dp(int u)
{
for(int i=0;i<son[u].size();++i)
{
f[u][0]=g[u][0][i],f[u][1]=g[u][1][i];
if(fa[u]) f[u][0]+=max(f[fa[u]][0],f[fa[u]][1]+d[u]),f[u][1]=f[u][0]+max(mx[u][i],f[fa[u]][0]+d[u]-max(f[fa[u]][0],f[fa[u]][1]+d[u]));
ans=max(ans,f[son[u][i]][0]+max(f[u][0],f[u][1]+d[son[u][i]])),dp(son[u][i]);
}
}
int main()
{
int i,n,u,v,w;n=read();
for(i=1;i<n;++i) u=read(),v=read(),w=read(),E[u].pb(pi(v,w)),E[v].pb(pi(u,w));
dfs(1),dp(1),cout<<ans;
}

Luogu P3647 [APIO2014]连珠线的更多相关文章

  1. [换根DP]luogu P3647 [APIO2014]连珠线

    题面 https://www.luogu.com.cn/problem/P3647 不重复地取树中相邻的两条边,每次得分为两条边权和,问最大得分 分析 容易想到状态 f[i][0/1] 分别表示 i ...

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

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

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

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

  4. 并不对劲的bzoj3677:p3647:[APIO2014]连珠线

    题目大意 有一种生成\(n\)个点的树的方法为: 一开始有一个点,\(n-1\)次操作,每次可以有两种操作:1.选一个点,用一条红边将它与新点连接:2.将新点放在一条红边上,新点与这条红边两端点直接的 ...

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

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

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

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

  7. 【LG3647】[APIO2014]连珠线

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

  8. 题解 [APIO2014]连珠线

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

  9. bzoj3677: [Apio2014]连珠线

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

随机推荐

  1. 【Python】PIL模块

    Python自建库,在爬虫等基础应用中更加简单好记,做整理以备自查. 目录 Image模块 open类.Save类.format类.Mode类.convert类.Size类.Info类.new类.Co ...

  2. crontab 常见 /dev/null 2>&1 详解

    大部分在 crontab 计划任务中都会年到未尾带 >/dev/null 2>&1,是什么意思呢? > 是重定向 /dev/null 代表空设备文件 1 表示stdout标准 ...

  3. Confluence备份,数据迁移

    一.Confluence的备份.恢复1)Confluence的备份 管理员账号登录Confluence,点击右上角的"一般配置"-"每日备份管理",如下图(默认 ...

  4. 前端性能优化 —— reflow(回流/重排)和repaint(重绘)

    简要:整个在浏览器的渲染过程中(页面初始化,用户行为改变界面样式,动画改变界面样式等)reflow(回流)和repaint(重绘) 会大大影响web性能,尤其是手机页面.因此我们在页面设计的时候要尽量 ...

  5. SQL中模糊查询的模式匹配

    SQL模糊查询的语法为: “Select column FROM table Where column LIKE 'pattern'”. SQL提供了四种匹配模式: 1. % 表示任意0个或多个字符. ...

  6. 【转载】使用 scikit-learn 进行特征选择

    [转载]使用 scikit-learn 进行特征选择 Read more: http://bluewhale.cc/2016-11-25/use-scikit-learn-for-feature-se ...

  7. Java连接MQTT服务-ws方式

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  8. 何为受控组件(controlled component)

    在 HTML 中,类似 , 和 这样的表单元素会维护自身的状态,并基于用户的输入来更新:当用户提交表单时,前面提到的元素的值将随表单一起被发送.但在 React 中会有些不同,包含表单元素的组件将会在 ...

  9. 在RHEL6_Oracle_Linux_6上生成正确的udev_rule_规则文件

    1. #首先确认是 Linux 6.0以上版本 [root@vrh6 dev]# cat /etc/issue          Oracle Linux Server release 6.2Kern ...

  10. 新建一个浏览器APP

    安卓开发环境准备好了,试试新建一个浏览器程序吧 1.Start a new Android Studio Project 2.选这个像微信一样的样式 3.选择语言和版本 4.等待创建完成,拖一个Web ...