[CTSC1997]选课【背包类树形dp】

[CTSC1997]选课

【树形 DP \text{DP} DP
一眼算法题(区分差分约束与拓扑排序)
注意到有些功课可能没有前置功课,于是把所有没有前置功课的点都与 0 \text{0} 0连边,然后进行树形 DP \text{DP} DP。注意到 0 \text{0} 0这个点要强制被选,那么最后选课个数就是 m+1 \text{m+1} m+1。注意这道题属于 01 \text{01} 01背包类树形 DP \text{DP} DP,以节点编号作为 DP \text{DP} DP阶段,像线性 DP \text{DP} DP一样,把当前背包的体积作为第二维状态,在状态转移的时候实际上就是一个分组背包问题。

#include <bits/stdc++.h>
using namespace std;
const int N=350;
int n,m,x,y,ans,f[N][N],sz[N],fir[N<<1],nxt[N<<1],to[N<<1],tot;
inline int read(){
	int cnt=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)){cnt=(cnt<<1)+(cnt<<3)+(c^48);c=getchar();}
	return cnt*f;
}
inline void add(int x,int y){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;}
void dfs(int u){
	for(int i=fir[u];i;i=nxt[i]){
		int v=to[i];
		dfs(v);sz[u]+=sz[v]+1;
		for(int j=max(m+1,sz[u]);j;--j){//倒序循环正确处理组内体积为0的物品
			for(int k=0;k<=j-1;++k){
				f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]);
			}
		}
	}
}
signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i) {x=read(),f[i][1]=read(),add(x,i);}
	dfs(0);
	printf("%d",f[0][m+1]);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值