loj10154 树形dp(多叉树转二叉树)

好久没有做关于树dp的题,一做就卡,裂开了。


本身这是一道简单的树背包问题。关于多叉转二叉,可以将一颗多叉树,某个结点的左儿子是它的某一个儿子,而他的右儿子是他的兄弟。

void makefa(int x,int fx) {
	rc[x] = lc[fx];
	lc[fx] = x;
}

这样,我们就成功将一个多叉的树转成了二叉树,在一些用二叉树做的题上很有优势。关于森林上如何动态规划的问题,可以添加一个空结点作为全祖先,然后将各棵树的头向该空结点相连即可。

点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<bitset>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>

using namespace std;
const int maxn = 105;
int m,n,rt;
int vl[maxn],lc[maxn],rc[maxn];
void makefa(int x,int fx) {
	rc[x] = lc[fx];
	lc[fx] = x;
}
int dp[maxn][maxn];
void dfs(int x,int y) {
	if((!x)||(!y)) return;
	if(dp[x][y]>0) return;
	dfs(rc[x],y);
	dp[x][y] = dp[rc[x]][y];
	for(int i=0;i<y;i++) {
		dfs(lc[x],i); dfs(rc[x],y-i-1);
		dp[x][y] = max(dp[x][y],vl[x]+dp[lc[x]][i]+dp[rc[x]][y-i-1]);
	}
}
int main(){
    scanf("%d%d",&m,&n);
    rt = m+1;
    for(int i=1;i<=m;i++) {
        int x; scanf("%d%d",&x,&vl[i]);
		if(x==0) x = rt;
		makefa(i,x);
	}
	dfs(rt,n+1);
	printf("%d",dp[rt][n+1]);
    return 0;
}
posted @ 2021-09-07 10:45  Newuser233  阅读(51)  评论(0编辑  收藏  举报