P2014 [CTSC1997] 选课
P2014 [CTSC1997] 选课 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这题的技巧:把这些没有父亲节点的点,把他们的父亲节点令为0,则可从多课树变成一棵树。
细节:由于0点是必须取的,所以m要加1
其他便是正常的背包树形dp
Code:
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second const int N=310; //const int M=; //const int inf=0x3f3f3f3f; //const ll INF=0x3ffffffffffff; int T,n,m,a[N],dp[N][N]; vector<int> g[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } void dfs(int x) { dp[x][1]=a[x]; for(auto v:g[x]) dfs(v); for(auto v:g[x]) for(int j=m;j;j--) for(int k=0;k<j;k++) dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[v][k]); } int main() { // freopen("","r",stdin); // freopen("","w",stdout); n=read(),m=read(); m++; for(int i=1;i<=n;i++) { int u=read(); a[i]=read(); g[u].pb(i); } dfs(0); printf("%d",dp[0][m]); return 0; }