Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3862 | Accepted: 2171 |
Description
Input
L K
It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line
0 0
Output
Sample Input
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output
5
【題意】
公司有n個人,每個人有價值vi,有一天舉辦年會,每個人都可以參加,但有嚴格的等級制度,參加活動時,不能同時出現a和a的上司,問如何才能使總和最大。
【分析】
每個人只有去和不去兩種狀態,設DP[i][0]和DP[i][1]分別表示第i個人不參加和參加年會,獲得的總的最大價值。
則狀態轉移方程爲:
DP[i][1] += DP[j][0],
DP[i][0] += max{DP[j][0],DP[j][1]};其中j爲i的孩子節點。
這樣,從根節點r進行dfs,最後結果爲max{DP[r][0],DP[r][1]}。
(分析來自yzmduncan)
第2~n+1行爲這n個人的價值
#include "stdio.h" //簡單的樹形dp題
#include "string.h"
#include "queue"
using namespace std;
#define N 60005
#define INF 0x3fffffff
struct node
{
int x,y;
int weight;
int next;
}edge[4*N];
int idx,head[N];
int root;
int du[N];
int value[N];
int dp[N][2];
int MAX(int a,int b) { return a>b?a:b; }
void Init()
{
idx = 0;
memset(head,-1,sizeof(head));
}
void Add(int x,int y,int weight)
{
edge[idx].x = x;
edge[idx].y = y;
edge[idx].weight = weight;
edge[idx].next = head[x];
head[x] = idx++;
}
void DFS(int i) //
{
int k,j;
dp[i][0] = 0;
dp[i][1] = value[i];
for(k=head[i]; k!=-1; k=edge[k].next)
{
j = edge[k].y;
DFS(j);
dp[i][0] += MAX(dp[j][0],dp[j][1]);
dp[i][1] += dp[j][0];
}
}
int main()
{
int n;
int i;
int x,y;
while(scanf("%d",&n)!=EOF)
{
Init();
memset(du,0,sizeof(du)); //記錄節點的入度
memset(dp,0,sizeof(dp));
for(i=1; i<=n; ++i)
scanf("%d",&value[i]);
while(scanf("%d %d",&x,&y) && x+y>0)
{
Add(y,x,0);
du[x]++;
}
for(i=1; i<=n; ++i)
{
if(du[i]==0)
root = i;
}
DFS(root);
printf("%d\n",MAX(dp[root][0],dp[root][1]));
}
return 0;
}