题意
在有必修的前提下,选择最多 m m m 门课程使得能获得学分最大。
思路
把正在枚举的这个儿子看成左子树,其它看成右子树,其实就把多叉树转换成了二叉树。
其他操作基本和它一样。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int w[100010],a[5010][5010],c[100010],f[5010][5010];
int sum[5010][5010],b[100010];
int n,m,x;
void dp(int x)
{
b[x]=1;
for(int i=1; i<=c[x]; i++)
{
int y=sum[x][i];
if(b[y]==1)
continue;
dp(y);
for(int j=m; j>=0; j--) //枚举当前父节点可以给儿子多少个学位
for(int k=j-1; k>=0; k--) //枚举左子树的学位分配
f[x][j]=max(f[x][j],f[y][k]+f[x][j-k-1]+a[x][y]);//j-k(右子树)不断合并左子树
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&x,&w[i]);
a[x][i]=w[i];
sum[x][++c[x]]=i;
}
dp(0);
cout<<f[0][m];
return 0;
}