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

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11743616.html

时间: 2024-10-13 07:08:34

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

【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,杪):-个新

[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的蓝线. 无论红线还是蓝线

APIO2014 连珠线

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

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,杪):

动态规划小练

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

luogu 1169 棋盘制作(单调栈/悬线)

luogu 1169 棋盘制作(单调栈/悬线) 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则.小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减一部分作为新棋盘,

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

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

[Luogu P4147] 玉蟾宫 (网格DP)

题面 传送门:https://www.luogu.org/problemnew/show/P4147 Solution 裸的求极大子矩阵 感谢wzj dalao的教学 首先,有一个很显然但很重要的结论,那就是求极大子矩阵肯定要贴着边或一个障碍点,否则就会浪费 根据这个定理,我们可以考虑一种做法 我们可以枚举每一个可放置的点 我们可以很轻松的得知它与它左边的障碍点(或边界)的距离,也可以得知它上面与下面能扩展到哪里(即无障碍点最多能到哪里) 那这个点能扩出的长方形的最大面积就是它左边的上面与下面能