题目:选课
思路:先把森林转成二叉树,再记忆化搜索。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;
struct Node{
int l,r,fa;
Node(){r=-1,l=-1,fa=-1;}
Node(int x,int y,int z){
l=x,r=y,fa=z;
}
};
int n,m;
vector<int> vec[305];
int a[305]={0};
int fa[305]={0};
Node t[305];
int f[305][305]={0};
void make_Tree(int x){ //森林 -> 二叉树
if(vec[x].size()==0) return ;
int c=vec[x][0];
t[x].l=c;
t[c].fa=x;
make_Tree(c);
for(int i=1;i<vec[x].size();i++){
int y=vec[x][i];
t[y].fa=c;
t[c].r=y;
c=y;
make_Tree(vec[x][i]);
}
}
int dfs(int x,int k){
if(x==-1) return 0;
if(f[x][k]!=-1) return f[x][k]; //记忆化搜索
if(k==0) return f[x][k]=0;
if(t[x].r==-1&&t[x].l==-1)
return f[x][k]=a[x];
f[x][k]=dfs(t[x].r,k); //不选x
for(int i=0;i<k;i++){ //选x
f[x][k]=max(f[x][k],dfs(t[x].l,i)+dfs(t[x].r,k-i-1)+a[x]);
}
return f[x][k];
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
a[i]=y;
vec[x].push_back(i);
}
make_Tree(0);
memset(f,-1,sizeof(f));
printf("%d",dfs(0,m+1));
return 0;
}