一种较为简洁且标准的思路,附代码
查看原帖
一种较为简洁且标准的思路,附代码
1768452
ZL_zhongyi楼主2025/8/1 14:17

首先

此题是树形dp(相信大家也看到了)

but

我们会发现在输入样例中,会出现多颗树

输入样例如图:

如果把它们当做森林进行遍历会比较麻烦, 所以我们将所有树的根节点连接到0号节点

这样就可以将森林变为树进行遍历。 剩下的就是深搜了

#include<bits/stdc++.h>
using namespace std;
int n,m;
int dp[303][303];//dp[i][j]表示以i为根,选j门课能获得的最大学分
vector<int>g[303];
void dfs(int x) {
	for(int i = 0; i < g[x].size(); i++) {
		int y = g[x][i]; //节点x的儿子
		dfs(y);
		for(int j = m+1; j >= 1; j--) { //DP,0节点必选,所以要选m+1个 
			for(int k = 0; k<j; k++) {
				dp[x][j]=max(dp[x][j],dp[y][k]+dp[x][j-k]);//最大值为(当前节点,儿子节点选k个子节点+当前节点选剩下j-k个儿子节点) 
			}
		}
	}
}
int main() {
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		int x, y;
		cin >> x >> y;
		dp[i][1] = y;
		g[x].push_back(i);//所有无根树的父节点是总根节点0  
	}
	dfs(0);
	cout << dp[0][m+1];
	return 0;
}

如有缺漏欢迎指正,希望大家能够喜欢

2025/8/1 14:17
加载中...