求助
查看原帖
求助
127925
Kio_楼主2020/11/23 12:48

fi,jf_{i,j} 表示以 ii 为根的子树内选 jj 个数能获得的最大价值,

可得转移 fi,jf_{i,j} == max$$\left\{f_{i,j}, f_{i,j-k}+ f_{y,k}\right\} + valxval_x

不知道上式有什么问题......求dalao指教 QwQ

#include<cstdio>
using namespace std;
const int maxn = 310;
int n,m;
int f[maxn][maxn]; 
int head[maxn], ver[maxn], nxt[maxn], tot, size[maxn];
int val[maxn];
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
void dfs(int x){
	size[x] = 1;
	//f[x][0] = val[x];
	for(int i=head[x];i;i=nxt[i]){
		int y=ver[i];
		dfs(y);
		size[x] += size[y];
		for(int j=size[x];j>=1;j--){ //一共选j个 
			for(int k=0;k<=min(j-1,size[y]);k++)//其中在子树y中选了k个,k!=j的原因是只有取根节点x才能取子树y,当k==j时相当于没取根节点x 
				f[x][j] = max(f[x][j], f[x][j-k] + f[y][k]);
				f[x][j] += val[x];
		}
	}
}
inline void addline(int u,int v){
	ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}
int read(){
	int num=0;
	char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while('0'<=c&&c<='9') num=num*10+(c&15), c=getchar();
	return num;
}
int main(){
	n=read(), m=read();
	for(int i=1;i<=n;i++){
		int ui=read();
		val[i]=read();
		addline(ui,i);
	}
	dfs(0);
	printf("%d",f[0][m+1]);
	return 0;
}
2020/11/23 12:48
加载中...