一道树形DP题。
f[i][j]表示i个点选j门课程的最大学分。
递推方程:
for(int a=n;a>0;a--)//总共选择多少 for(int b=0;b<a;b++)//分别选择多少(b,a-b) f[x][a]=max(f[x][a],f[x][a-b]+f[u][b]); //都不遍历0的原因是f[i][0]无论怎样都是0
我们可以证明在j<=m时值都是正确的,剩下的不用管啦么的时间!
1 #include<iostream> 2 #include<cstdio> 3 #include<ctype.h> 4 #include<vector> 5 #include<algorithm> 6 #include<cstring> 7 using namespace std; 8 const int maxn=305; 9 inline int read() 10 { 11 int x,w=1;char c=getchar(); 12 while(!isdigit(c))c=getchar(); 13 if(c=='-')w=-1,c=getchar(); 14 x=c-'0';c=getchar(); 15 while(isdigit(c))x=x*10+c-'0',c=getchar(); 16 return x*w; 17 } 18 int n,m; 19 int f[maxn][maxn]; 20 vector <int>son[maxn]; 21 void dfs(int x) 22 { 23 f[x][0]=0; 24 for(int i=0;i<son[x].size();i++) 25 { 26 int u=son[x][i]; 27 dfs(u); 28 for(int a=n;a>0;a--) 29 for(int b=0;b<a;b++) 30 f[x][a]=max(f[x][a],f[x][a-b]+f[u][b]); 31 } 32 } 33 int main() 34 { 35 n=read(),m=read()+1; 36 for(int i=1;i<=n;i++){ 37 son[read()].push_back(i); f[i][1]=read(); 38 } 39 f[0][0]=f[0][1]=0; 40 n++; 41 dfs(0); 42 printf("%d\n",f[0][m]); 43 return 0; 44 }