トピックリンク:
http://acm.hdu.edu.cn/showproblem.php?pid=1520
結婚記念日
制限時間:2000/1000 MS(Java /その他)メモリ制限:65536/32768 K(Java /その他)合計送信数:11790承認された送信数:4826
問題の説明
ウラル州立大学80周年を祝うパーティーが開催されます。大学は従業員の階層構造を持っています。これは、監督者の関係が、レチャコフ美術館に根ざしたツリーを形成することを意味します。パーティーをみんなにとって面白くするために、牧師は従業員とその直属の上司の両方が出席することを望んでいません。人事部では、社員一人ひとりの共生を評価しているので、全員に番号(格付け)をつけています。あなたの仕事は、ゲストの陽気さの評価の可能な最大の合計でゲストのリストを作成することです。
入力
従業員には1からNまでの番号が付けられます。入力の最初の行には番号Nが含まれます。1<= N <=6000。後続の各N行には、対応する従業員の陽気度が含まれます。共生評価は、-128から127の範囲の整数です。その後、スーパーバイザー関係ツリーを説明するT行に進みます。ツリー仕様の各行の形式は次のとおりです
。LKK
番目の従業員がL番目の従業員の直属の上司であることを意味します。入力は行
00で終了し ます
。LKK
番目の従業員がL番目の従業員の直属の上司であることを意味します。入力は行
00で終了し ます
出力
出力には、ゲストの評価の最大合計が含まれている必要があります。
サンプル入力
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
サンプル出力
5
トピックの主なアイデア:n人がいて、それぞれがvalの値を持っています。パーティーに参加するためにそれらから何人かの人を選択してください。同時に上司に直接関係している2人の従業員を選択することはできません。時間。これらの従業員の値の合計の最大値を見つけます
//树状DP入门
//通过递归计算以i为根的子树,选了第i人或者没选第i人的最大值
#include <stdio.h>
#include <vector>
#include <algorithm>
#define maxn 6005
#define inf 0x3f3f3f3f
using namespace std;
vector<int> G[maxn];
bool vis[maxn];
int val[maxn];
int dp[maxn][2]; //dp[i][0]表示选了第i人,dp[i][1]表示没拿第i人
void dfs(int root)
{
int l = G[root].size();
dp[root][0] = val[root];
for(int i=0; i<l; i++)
dfs(G[root][i]);
for(int i=0; i<l; i++)
{
int u = G[root][i];
dp[root][0] += dp[u][1];
dp[root][1] += max(dp[u][0], dp[u][1]);
}
}
int main()
{
int n;
while(scanf("%d", &n)!=EOF)
{
for(int i=0; i<maxn; i++)
{
G[i].clear();
vis[i] = 0;
dp[i][0] = 0;
dp[i][1] = 0;
}
for(int i=1; i<=n; i++)
{
scanf("%d", &val[i]);
}
for(;;)
{
int l, k;
scanf("%d%d", &l, &k);
if(k==0 && l==0)
break;
G[k].push_back(l);
vis[l] = 1;
}
int ans = 0;
for(int i=1; i<=n; i++)
if(!vis[i])
{
dfs(i);
ans += max(dp[i][0], dp[i][1]);
}
printf("%d\n", ans);
}
return 0;
}