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
題目大意:
題目大概說的是,一個公司要舉行一個party ,讓每個人參加的話就會增加一定的歡樂程度,爲了排除尷尬的場面,每個人和他的直接領導不能同時來參加,給你一個 n ,說明有 n 個人,然後 接着 n 行 表示 讓每個人去所增加的歡樂程度,接着每行輸入兩個說 l 和 k ,表示 k 是 l 的直屬上司,直到輸入爲 0 0 時該組輸入結束,輸出所能達到的最大的歡樂值。
思路分析:
每個人能不能參加與他的直屬上司參加不參加有關,如果他的上司參加了,那麼他就不能參加,如果他的上司沒參加,那麼他可以參加也可以不參加,我們現在用 dp[i][0] 表示 i 不參加的歡樂值,dp[i][1] 表示 i 參加的歡樂值,那麼我們可以推出一個狀態轉移方程
dp[k][1] += dp[l][0];
dp[k][0] += max(dp[l][0],dp[l][1]);
因此,我們就可以用這個狀態轉移方程求解。
這道題出現了一個令我很無語的情況,那就是在 HDU oj 上 用 c++ 編譯器能過,而用 G++ 編譯器超時,所以大家提交的時候注意點
附上一些我找到的 c++ 與 g++ 的差別鏈接:http://blog.csdn.net/xia842655187/article/details/51329012點擊打開鏈接
附上代碼:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;
int dp[6500][2];
int visit[6500],n,father[6500];
void dfs(int root) // 利用 深搜從根開始往下搜,搜到最後一層厚,慢慢的網上遞推轉移
{
visit[root] = 1;
for(int i = 1;i <= n;i++)
{
if(father[i] == root && !visit[i]) // root 是 i 的上司,那麼就對 i 作爲一個新根進行往下搜索
{
dfs(i);
dp[root][1] += dp[i][0]; // root 去的時候,i 肯定不能去,所以 加上 dp[i][0]
dp[root][0] += max(dp[i][0],dp[i][1]); // root 不去的時候 從 i 去和不去中選一個最大值
}
}
}
int main()
{
while(cin >> n)
{
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;i++)
{
scanf("%d",&dp[i][1]);
}
fill(father,father + 6500,0); // 將每個人的直屬上司初始化爲 0
int l ,k,root = 0;
while(cin >> l >> k && l + k) // 對 每個人的直屬上司進行標記
{
father[l] = k;
root = k;
}
while(1) // 判斷查詢到樹的根
{
if(father[root] == 0)
break;
root = father[root];
}
memset(visit,0,sizeof(visit));
dfs(root); // 從根開始查詢
cout << max(dp[root][0],dp[root][1]) << endl; // 從 大 boss 去與不去中選擇一個 歡樂值最大的輸出
}
return 0;
}