给一棵二叉树,给一个非0 integer K,K代表选取相连的K个节点,求K个子节点组成和最大的子树
比如这张图,在K为5的情况下,最大子树是3,4,8,10,2
树dp。dp[i][j]表示以第i号节点为根、大小为j的连通子图(这里不能称为子树,故称连通子图)的最大权值和。那么有dp[i][j]=max(dp[lson[i]][p]+dp[rson[i]][j-1-p]),0<=p<=j-1。
题目要选的大小为k的连通子图必然以某一点为根,所以,dp[i][k](1<=i<=n)的最大值即为答案。
代码如下
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
const int INF=0x3f3f3f3f;
int son[N][2],n,k;
int val[N],dp[N][110],choose[N][110];
void dfs(int x)
{
if(!x)return;
dfs(son[x][0]);
dfs(son[x][1]);
dp[x][0]=0;
for(int i=1;i<=k;i++)
{
dp[x][i]=-INF;
for(int j=0;j<i;j++)
{
if(dp[son[x][0]][j]+val[x]+dp[son[x][1]][i-j-1]>dp[x][i])
{
dp[x][i]=dp[son[x][0]][j]+val[x]+dp[son[x][1]][i-j-1];
choose[x][i]=j;
}
}
}
}
void dfs1(int x,int nb)
{
if(!nb)return;
printf("%d %d\n",x,val[x]);
dfs1(son[x][0],choose[x][nb]);
dfs1(son[x][1],nb-1-choose[x][nb]);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",val+i);//read the value on each node
for(int i=1;i<=n;i++)scanf("%d%d",&son[i][0],&son[i][1]);//read the id of each node's sons, 0 for not having this son
for(int i=1;i<=k;i++)dp[0][i]=-INF;
dp[0][0]=0;
dfs(1);
int ans=-INF,flg=0;
for(int i=1;i<=n;i++)
{
if(dp[i][k]>ans)
{
ans=dp[i][k];
flg=i;
}
}
printf("%d\n",ans);//the max sum
dfs1(flg,k);
return 0;
}
/*
9 5
2 3 5 4 8 3 6 10 2
2 3
4 5
6 7
8 9
0 0
0 0
0 0
0 0
0 0
*/
递归一下:https://blog.csdn.net/andahuzhuang/article/details/52037394