树形DP:k结点子树最大权值和

很基础的一类题目,要用到01背包问题的思想。

ZOJ3201

题解

  • 含有k个结点的权值和最大的子树。
  • dp[i][j]表示以i为根的,含有j个结点的最大权值
  • dp[i][j] = max(dp[i][j],dp[i][j-k] + dp[v][k])。v是i的子结点。类似于分组背包问题,每个结点算一个组,每个组又有很多种选择。

代码

#include 
using namespace std;
int const N = 100 + 10;
int n,k,dp[N][N],sz[N],ans;
vectorG[N];
void dfs(int u,int fa){
	sz[u] = 1;
	for(int i=0;i=1;j--){
			for(int k=1;k

ural1018

题解

  • 以1为根保留的q条边的最优值
  • 相当于保留q+1个结点。
  • 和上面一毛一样。只不过这里是边有权值,上边是点有权值

代码

#include 
using namespace std;
int const N = 100 + 10;
int n,q,dp[N][N],sz[N];   
struct Node
{
	int to,val;	
	Node(){}
	Node(int to,int val):to(to),val(val){}
};
vectorG[N];
void dfs(int u,int fa){
	sz[u] = 1;
	for(int i=0;i1;j--){    //枚举子树的大小,要有根必须有两个结点
			for(int k=1;k

HDU1561

题解

  • 0为根含有m+1个结点的最大子树

代码

#include 
using namespace std;
int const N = 200 + 10;
int n,m,dp[N][N],sz[N];
vectorG[N];
void dfs(int u,int fa){
	sz[u] = 1;
	for(int i=0;i=1;j--){
			for(int k=1;k

 

你可能感兴趣的:(DP)