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}\)如何求?
我们这样考虑:穿过\(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]连珠线的更多相关文章
- [换根DP]luogu P3647 [APIO2014]连珠线
题面 https://www.luogu.com.cn/problem/P3647 不重复地取树中相邻的两条边,每次得分为两条边权和,问最大得分 分析 容易想到状态 f[i][0/1] 分别表示 i ...
- 洛谷$P3647\ [APIO2014]$连珠线 换根$dp$
正解:换根$dp$ 解题报告: 传送门! 谁能想到$9102$年了$gql$居然还没写过换根$dp$呢,,,$/kel$ 考虑固定了从哪个点开始之后,以这个点作为根,蓝线只可能是直上直下的,形如&qu ...
- 洛谷 P3647 [APIO2014]连珠线(换根 dp)
题面传送门 题意: 桌子上有 \(1\) 个珠子,你要进行 \(n-1\) 次操作,每次操作有以下两种类型: 拿出一个新珠子,并选择一个桌子上的珠子,在它们之间连一条红线 选择两个由红线相连的珠子 \ ...
- 并不对劲的bzoj3677:p3647:[APIO2014]连珠线
题目大意 有一种生成\(n\)个点的树的方法为: 一开始有一个点,\(n-1\)次操作,每次可以有两种操作:1.选一个点,用一条红边将它与新点连接:2.将新点放在一条红边上,新点与这条红边两端点直接的 ...
- 【BZOJ3677】[Apio2014]连珠线 换根DP
[BZOJ3677][Apio2014]连珠线 Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做“连珠线”.不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色 ...
- [Bzoj3677][Apio2014]连珠线(树形dp)
3677: [Apio2014]连珠线 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 434 Solved: 270[Submit][Status] ...
- 【LG3647】[APIO2014]连珠线
[LG3647][APIO2014]连珠线 题面 洛谷 题解 首先考虑一下蓝线连起来的情况,一定是儿子-父亲-另一个儿子或者是儿子-父亲-父亲的父亲. 而因为一开始只有一个点在当前局面上,将一条红边变 ...
- 题解 [APIO2014]连珠线
题解 [APIO2014]连珠线 题面 解析 首先这连成的是一棵树啊. 并且\(yy\)一下,如果钦定一个根, 那么这上面的蓝线都是爸爸->儿子->孙子这样的,因为像下图这样的构造不出来: ...
- bzoj3677: [Apio2014]连珠线
Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做“连珠线”.不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色和蓝色.游戏 开始时,只有1个珠子,而接下来新的 ...
随机推荐
- IE8 浏览器文本模式变为杂项(quirks)页面变形的解决方法
IE8 浏览器文本模式(document.documentMode)变为杂项(quirks)页面变形的解决方法. 正常情况下 document.documentMode 输出为8,而变为杂项之后doc ...
- 【WC2016】论战捆竹竿
已经快三周了啊--终于把挖的坑填了-- 首先显然是把除了自身的所有border拿出来,即做 \(\left\{ n - b_1, n - b_2, \dots, n - b_k, n \right\} ...
- 论文阅读:NETFPGA SUME: TOWARD 100 GBPS AS RESEARCH COMMODITY
摘要: 数据中心网络的需求增长意味着许多组成技术不在研究社区的预算之内. NETFPGA SUME是基于FPGA的PCI Express板,具有I / O功能,可作为网络接口卡,多端口开关,防火墙或测 ...
- 【Python】爬虫汇总
主要流程: 获取url下载网页从网页中找寻自己需要的保存(解析+输出)主要概念URL:分大小写统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联 ...
- stack和queue小讲
由于stack和queue没有太多新的东西,故在此只把API拿出来小说一下,自己也记得比较牢靠一些. stack常用API push(int elem); //向栈顶添加元素 pop(); //从栈顶 ...
- Python列表解析和字典解析
python笔记_列表解析 相比于for循环,列表解析的语法是由底层c语言实现的,它和使用for循环遍历pyobject对象相比,性能会有很大的提升. 无条件子句的列表解析式 In [2]: [2*i ...
- go.js-拖拽流程图插件
1.去除水印 在文件中搜索7eba17a4ca3b1a8346,找到类似a.Jv=d[w.Jg("7eba17a4ca3b1a8346")][w.Jg("78a118b7 ...
- 微信小程序底部菜单栏的使用方法
1.找到项目根目录的配置文件 app.json,在配置文件中加入配置代码.例如: "tabBar": { <!--底部的导航配置属性--> "color&qu ...
- windows spark1.6
jdk1.7 scala 2.10.5 spark 1.6.1 http://spark.apache.org/downloads.html hadoop 2.6.4 只需要留bin https:// ...
- 解决phpmyadmin出现: Maximum execution time of 300
在mysql用phpmyadmin导入数据的时候出现: Fatal error: Maximum execution time of 300 seconds exceeded in ... 上网查了很 ...