1352.Stalingrad: Enemy at the Gates
Description
Enemy at the gates!
King James let you be the general of the Royal Army to defend the country, you know the fighting capacity of the soldiers, you need to maximizing the total fingting capacity of the Royal Army, of course, he can also send himself. The limit is, if one soldier was sent to the war, then his superior can not be sent, and the general has no superior.
Your task is to help the general know the maximum fingting capacity there will be.
The 1st line, an integer N ( 1<=N<=6000 ), the number of soldiers in the Royal Army.
The next N lines, each line has an integer x ( -128<=x<=127 ), the fighting capacity of the i-th soldier.
Then, there are multiple lines and these lines ending with 0 0, each line has two integers, L and K, said that the K-th soldier is the L-th soldier's superior.
One integer, the maximum fingting capacity.
11
2
3
1
1
1
4
1
5
-2
5
2
1 3
2 3
3 5
6 4
9 6
10 7
7 4
8 4
11 8
4 5
0 0
Sample Output
20
题意是说有n个士兵,下面n行把他们各自的能力表示出来,然后下面再跟的是第l个士兵的上级是第k个士兵。在派遣的时候如果派了一个士兵,那么这个士兵的上一级就不能再派遣,问最大派遣的能力是多少。
以前也做过类似的题,看题意很清楚这是个树状DP的题目,然后把派遣和不派遣的能力都用dp数组排出来就好了。不过.....虽然做过但是还是不会建树= =好吧,一直是自己的薄弱点,这次再写这个博客出来的原因也是该好好学学建树了,于是上网又学了下,下面代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int father[6005];
int dp[6005][2];
bool vis[6005];
int dfs(int root)
{
int i,j;
vis[root]=1;
for(i=1;i<=n;i++)
{
if(!vis[i]&&father[i]==root)
{
dfs(i);
dp[root][1]=dp[root][1]+dp[i][0];
dp[root][0]=dp[root][0]+max(dp[i][0],dp[i][1]);
}
}
return 0;
}
int main()
{
int i,j,l,k,root;
while(scanf("%d",&n)!=EOF)
{
root=0;
memset(vis,0,sizeof(vis));
memset(father,0,sizeof(father));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
scanf("%d",&dp[i][1]);
}
while(scanf("%d%d",&l,&k))
{
if(l==0&&k==0)
break;
father[l]=k;
if(father[k]==0)
root=k;
}
dfs(root);
cout<<max(dp[root][0],dp[root][1])<<endl;
}
return 0;
}