题解没有上司的舞会

Posted cjtcalc

tags:

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

期末考前写题解,(rp++)
[ description ]
给出一棵点带权树,你需要选取若干个点:

(<1> :) 选取的点两两不具有父子关系

(<2> :) 在满足 (<1>) 的情况下最大化点权和

求最大的点权和。
[ solution ]
树形 (dp) 经典。

f[u][0] 表示在不选 (u) 的情况下,在以 (u) 为根的子树中取点的最大点权和。

f[u][1] 表示在选取 (u) 的情况下,在以 (u) 为根的子树中取点的最大点权和。

若不选 (u) ,则对于 (u) 的任意一个儿子,取不取都不会与 (u) 形成父子关系,则有状态转移方程:
[ f[u][0]=sum_{v=operatorname{son}(u)}operatorname{max}(f[v][0],f[v][1]) ]
若选取 (u) ,则不能选取 (u) 的任意一个儿子,则有状态转移方程:
[ f[u][1]=val[u]+sum_{v=operatorname{son}(u)}f[v][0] ]
答案为 (operatorname{max}(f[root][0],f[root][1]))

一次树形 (dp) 即可解决。
[ code ]

#include<cstdio>
#include<algorithm>

#define RI register int

using namespace std;

inline int read()
{
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}

const int N=6100,M=6100;

int n;

int val[N];

bool sig[N];

int tot,head[N],ver[M],Next[M];

void add(int u,int v)
{
    ver[++tot]=v;    Next[tot]=head[u];    head[u]=tot; 
}

int f[N][2];

void dp(int u)
{
    f[u][0]=0;
    f[u][1]=val[u];
    for(RI i=head[u];i;i=Next[i])
    {
        int v=ver[i];
        dp(v);
        f[u][0]+=max(f[v][0],f[v][1]);
        f[u][1]+=f[v][0];
    }
}

int main()
{
    n=read();

    for(RI i=1;i<=n;i++)
        val[i]=read();

    for(RI i=1;i<n;i++)
    {
        int u=read(),fa=read();
        sig[u]=true,add(fa,u);
    }

    read(),read();

    int root;
    for(RI i=1;i<=n;i++)
    if(sig[i]==false)
    {
        root=i;
        break;
    }

    dp(root);

    printf("%d
",max(f[root][0],f[root][1]));

    return 0;
}

[ thanks for watching ]

以上是关于题解没有上司的舞会的主要内容,如果未能解决你的问题,请参考以下文章

SSL题解报告没有上司的舞会

题解没有上司的舞会

P1352 没有上司的舞会 题解

没有上司的舞会——树状DP 入门题,真的比想象中简单许多

没有上司的舞会

P1352 没有上司的舞会