1. 程式人生 > >選課 洛谷p2014

選課 洛谷p2014

題目描述

在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有N門功課,每門課有個學分,每門課有一門或沒有直接先修課(若課程a是課程b的先修課即只有學完了課程a,才能學習課程b)。一個學生要從這些課程裡選擇M門課程學習,問他能獲得的最大學分是多少?

輸入輸出格式

輸入格式:

 

第一行有兩個整數N,M用空格隔開。(1<=N<=300,1<=M<=300)

接下來的N行,第I+1行包含兩個整數ki和si, ki表示第I門課的直接先修課,si表示第I門課的學分。若ki=0表示沒有直接先修課(1<=ki<=N, 1<=si<=20)。

 

輸出格式:

 

只有一行,選M門課程的最大得分。

 

輸入輸出樣例

輸入樣例#1: 複製

7  4
2  2
0  1
0  4
2  1
7  1
7  6
2  2

輸出樣例#1: 複製

13

 

#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
#define ff(i,r,l) for(i=(r);i>=(l);i--)
using namespace std;
const int MAXN=305;
struct Edge{
	int v,w,nxt;
}e[MAXN<<1];
int h[MAXN],tot,a[MAXN];
int n,m;
int dp[MAXN][MAXN],size[MAXN];
inline void add(int u,int v)
{
	e[tot].v=v;
	e[tot].nxt=h[u];
	h[u]=tot++;
}
void dfs(int u,int fa)
{
	int i,j,k;
//	cout<<u<<"GG"<<endl;
	dp[u][1]=a[u];
	size[u]=1;
	for(i=h[u];~i;i=e[i].nxt){
		int v=e[i].v;
//		cout<<v<<"GGG"<<endl; 
		if(v==fa) continue;
		dfs(v,u);
		size[u]+=size[v];
		ff(j,size[u],2){
			f(k,1,j-1){
				dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	memset(h,-1,sizeof(h));
	int i,j,u,w;
	cin>>n>>m;
	f(i,1,n){
		cin>>u>>a[i];
		add(u,i);
		add(i,u);
	}
	dfs(0,-1);
	cout<<dp[0][m+1]<<endl;
	return 0;
 }