AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 286. 选课    原题链接    中等

作者: 作者的头像   youlinse ,  2019-10-15 09:15:50 ,  所有人可见 ,  阅读 2441


10


4

286选课

题目简述

n个点选m个,求最大权值
要求: x选了,fa[x]也必须选

dp常规写法:(dp[i][j]表示i的子树选j个)

for(int i=m;i>=0;i--)
    for(int j=1;j<=i;j++)
        f[x][i]=max(f[x][i],f[x][i-j]+f[v][j] );
//v是x的孩纸
for(int i=m;i;i--)
    f[x][i]=f[x][i-1]+w[x];

此时时间复杂度O(nm^2)

一种神奇的优化

对树进行后序遍历
令l[x]=dfn[x]-size[x];
即l[x]表示在i节点的子树之前遍历的最后一个dfs序
(可以自己看一下dfn[x]-size[x]得到的dfn是哪个节点)

f[i][j] 表示前i个遍历的节点代价为j的最大值

f[i][j]=max(f[l[x]][j] (当前节点不选,则子树都不能选),f[i-1][j-1]+w[x] (选当前节点)) 注:x=dfn[i];

时间复杂度

O(nm)的优秀复杂度

C++ 代码

#include<bits/stdc++.h>
using namespace std;
int read()
{
    int ans=0;
    char c=getchar();
    while(c<'0'||c>'9')
    c=getchar();
    while(c>='0'&&c<='9')
    {
        ans=(ans<<1)+(ans<<3)+c-'0';
        c=getchar();
     } 
     return ans;
}
const int N=305; 
int n,m,cnt,num,last;
int head[N],to[N],nex[N],w[N];
int f[N][N],sz[N],dfn[N];
void add(int x,int y)
{
    cnt++;
    nex[cnt]=head[x];
    head[x]=cnt;
    to[cnt]=y;
}
void dfs(int x)//后序遍历
{
    sz[x]=1;
    for(int i=head[x];i;i=nex[i])
    {
        dfs(to[i]);
        sz[x]+=sz[to[i]];
    }
    dfn[++num]=x;
} 
int main()
{
    n=read(),m=read()+1;
    for(int i=1;i<=n;i++)
    {
        int x=read();
        w[i]=read();
        add(x,i);
    }
    dfs(0);
    for(int i=1;i<=n+1;i++)//i是遍历顺序
        for(int j=min(m,i);j>=1;j--)
            f[i][j]=max(f[i-sz[dfn[i]]][j],f[i-1][j-1]+w[dfn[i]]);  
    printf("%d",f[n+1][m]);//n+1因为有0号节点,之前m也有+1的;
    return 0;
}

3 评论


用户头像
TKater_yzt   2022-11-15 20:54         踩      回复

很有用的一种优化,如果我没记错的话,洛谷上有一个苹果树的树形DP就是利用了后序遍历进行了优化


用户头像
江忍忍   2022-11-06 11:33         踩      回复

秀,tql


用户头像
rookie升职记   2021-01-03 17:08         踩      回复

秀,太优秀了,Orz,膜拜大佬


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息