APIO2014 连珠线

Posted 风浔凌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了APIO2014 连珠线相关的知识,希望对你有一定的参考价值。

题目链接:戳我

换根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
",ans);
    return 0;
}

以上是关于APIO2014 连珠线的主要内容,如果未能解决你的问题,请参考以下文章

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

[APIO2014]连珠线

bzoj3677: [Apio2014]连珠线

APIO2014 连珠线

Luogu P3647 [APIO2014]连珠线

动态规划小练