loj10154 樹形dp(多叉樹轉二叉樹)
阿新 • • 發佈:2021-09-07
好久沒有做關於樹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; }