Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 7291 | Accepted: 4195 |
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
樹形DP,實際上就像是把入門級的數塔放在了樹上。
記dp[ i ][ 0 ]爲 i 不去的下屬的最大活躍度和。
記dp[ i ][ 1 ]爲 i 去的時候,i 及其下屬的最大活躍度和。
若 j 爲 i 的直接下屬。
dp[ i ][ 1 ] = dp[ j ][ 0 ] // 如果 i 去了,她的直接下屬 i 不能去。
dp[ i ][ 0 ] = max ( dp[ j ][ 1 ] ,dp[ j ][ 0 ] ) //如果 i 不去,那她的直接下屬可以去或者不去。
我們從葉子節點開始,一直向根節點進行決策。
AC代碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int par[6066];
bool vis[6066];
int dp[6066][3];
int n;
void init(int n)
{
for(int i=1;i<=n;i++)
{
par[i]=i;//初始化i的父節點爲i(我參考的並查集的寫法)
vis[i]=0;//檢查i是否已經進行過決策
dp[i][1]=0;
dp[i][0]=0;
}
}
void dfs(int root)
{
vis[root]=1;
for(int i=1;i<=n;i++)
{
if(!vis[i]&&par[i]==root)
{
dfs(i);//dfs要在前,更新DP要在後。因爲我們是從葉子節點開始的。
dp[root][1]+=dp[i][0];
dp[root][0]+=max(dp[i][0],dp[i][1]);
}
}
}
int main()
{
while(~scanf("%d",&n))
{
init(n);
int a,b;
for(int i=1;i<=n;i++)
{
scanf("%d",&dp[i][1]);
}
while(scanf("%d%d",&a,&b)&&(a||b))
{
par[a]=b;
}
int root=1;
while(par[root]!=root)
{
root=par[root];
}
dfs(root);
printf("%d\n",max(dp[root][1],dp[root][0]));
}
return 0;
}