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;
}