轉自:http://www.cnblogs.com/qscqesze/p/4971434.html
邱老師玩遊戲
Time Limit: 20 Sec
Memory Limit: 256 MB
題目連接
http://acm.uestc.edu.cn/#/problem/show/1136
Description
邱老師最近在玩一種戰略遊戲,在一個地圖上,有N座城堡,每座城堡都有一定的寶物,在每次遊戲中邱老師允許攻克M個城堡並獲得裏面的寶物。
但由於地理位置原因,有些城堡不能直接攻克,要攻克這些城堡必須先攻克其他某一個特定的城堡。你能幫邱老師算出要獲得儘量多的寶物應該攻克哪M個城堡嗎?
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
對於每個測試實例,輸出一個整數,代表邱老師攻克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
分析:其實就是冬季賽的樹的揹包的題目。
vector<int> Q[205];
long long dp[205][205];
int vis[205];
int b[205];
int n,m;
void dfs(int x)
{
if(vis[x])return;
vis[x]=1;
dp[x][1]=b[x];
for(int i=0;i<Q[x].size();i++)
{
int v = Q[x][i];
dfs(v);
for(int j=m;j>=0;j--)
for(int k=0;k<j;k++)
dp[x][j]=max(dp[x][j],dp[v][k]+dp[x][j-k]);
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)break;m++;
for(int i=0;i<=n;i++)
Q[i].clear();
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
int x;scanf("%d%d",&x,&b[i]);
Q[x].push_back(i);
}
dfs(0);
printf("%lld\n",dp[0][m]);
}
}