hdu 1561 The more,The BetterツリーDP+リュックサック

2394 ワード

The more, The Better
Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3511    Accepted Submission(s): 2056
Problem Description
ACboyは戦略ゲームが大好きで、1つの地図の上で、Nつの城があって、すべての城はすべて一定の宝物があって、毎回ゲームの中でACboyはMつの城を攻略して中の宝物を得ることを許可します.しかし、地理的な理由で、直接攻略できない城もあります.これらの城を攻略するには、まず他の特定の城を攻略しなければなりません.できるだけ多くの宝物を手に入れるにはどのM城を攻略すべきか、ACboyに計算してもらえますか?
 
Input
各試験例は、まず、2つの整数、N、M.(1<=M<=N<=200)を含む.次のN行では、各行に2つの整数が含まれ、a,b.i行目では、aはi番目の城を攻略するにはまずa番目の城を攻略しなければならないことを表し、a=0であればi番目の城を直接攻略することができることを表す.bはi番目の城の宝物の数を表し、b>=0である.N=0でM=0入力が終了します.
 
Output
各試験例について、ACboyがM個の城を攻略して得た最も多くの宝物の数を表す整数を出力する.
 
Sample Input

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

 
Sample Output

   
   
   
   
5 13

 
#include<stdio.h>
#include<string.h>
#define size 210
struct node{
	int from,to,next;
}edge[size];
int head[size];  //head[i]   i             
int m,tot,n,a,b;
//                 
int dp[size][size],f[size][size],w[size],vis[size];
void addEdge(int fa,int ch)
{
	edge[tot].from=fa;         //    
	edge[tot].to=ch;           //    
	edge[tot].next=head[fa];   //tot  a         
	head[a]=tot++;             //head[a]        
}
int max(int a,int b)
{
	return a>b?a:b;
}
void dfs(int u)
{
	int i,j,k,r;
	vis[u]=1;
	for(i=head[u];i!=-1;i=edge[i].next)
	{
		r=edge[i].to;
		if(!vis[r])
			dfs(r);
		for(j=m;j>=1;j--)              //r          ,    ,   f[u][j-k]    r  
		{
			for(k=1;k<=j;k++)
			{
				f[u][j]=max(f[u][j],f[u][j-k]+dp[r][k]);
			}
		}
	}
	for(i=m+1;i>=1;i--)
	{
		dp[u][i]=max(dp[u][i],f[u][i-1]+w[u]);  //     ,  dp[u]
	}
}
int main()
{
	int i,j,k,l;
	while(scanf("%d %d",&n,&m)&&n||m)
	{
		memset(dp,0,sizeof(dp));
		memset(head,-1,sizeof(head));
		memset(f,0,sizeof(f));
		memset(vis,0,sizeof(vis));
		memset(w,0,sizeof(w));
		tot=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d %d",&a,&b);
			addEdge(a,i);
			w[i]=b;
		}
		dfs(0);
		printf("%d
",dp[0][m+1]); } return 0; }