公司聚會
Description
dd_engi所在的TIANYI公司要舉辦一次盛大的公司聚會。可惜的是,由於場地和花費的原因,不可能所有人都參加。現在的任務是擬定參加聚會人員的名單。
TIANYI公司的組織架構可以看做一棵有根多叉樹。也就是說,在編號爲1~N的所有N名員工中,除了最高管理者(編號爲1)以外,每個員工都有且僅有一位直接上司;最高管理者則是這棵多叉樹的“根”。這很好理解,對嗎?另外,我們保證,員工的編號會大於他的直接上司的編號。
不同的員工對於聚會有着不同的要求,事實上,若邀請第i位員工(編號爲i),在聚會中滿足他的要求需要花費Ci元。另一方面,不同的員工在聚會中的“興奮指數”也不同,第i位員工參加聚會的興奮指數是Ei。
選擇參加聚會的人員還有一個限制:爲了使參加聚會的員工能夠儘量放鬆,若邀請了某位員工,就不能邀請他的任何一位上司。這裏“上司”的定義是這樣的:最高管理者沒有上司,其餘所有員工的直接上司以及直接上司的所有上司都是他的上司。換句話說,某位員工的上司就是樹中從他的節點走到根節點的路徑上經過的所有節點(包括根結點,但不包括他自身)。
在滿足上述限制的前提下,dd_engi希望參加聚會人員的興奮指數之和最大,但同時他被告知,滿足所有參加聚會人員的要求的總花費不得超過M元。那麼,參加聚會人員的名單究竟應該怎樣確定才最優呢?你需要求出的是最大的總興奮指數。
Input
第一行,兩個空格隔開的整數,N與M。
第二行,N-1個整數,分別是第2位至第N位員工的直接上司的編號。
第三行,N個整數,分別是C1、C2……CN。
第四行,N個整數,分別是E1、E2……EN。
Output
只需輸出一行一個整數,即最大的總興奮指數。
Sample Input
10 100
1 2 2 1 4 3 5 6 1 12 53 127 32 164 22 199 10 19 17 -1 0 3 5 7 -2 9 6 8 13
Sample Output
27
Answer
/**
感覺這個題迷迷糊糊就寫過了
dp[i][j]代表以i爲根節點的子樹上面花費j元所能得到的最大的興奮值
那麼i從1~n,當i一定時,要麼只邀請根節點,要麼邀請他的子樹們
邀請根節點的很好寫,
邀請子樹的,就成了有1~vec[i].size()件物品,花費爲j能達到的最大值的01揹包
那麼對於每一個子樹,他的花費v需要從0到m枚舉,對應的值爲dp[p][v];
具體見代碼
**/
#include
#define maxn (10000 + 10)
using namespace std;
vector Vec[maxn];
struct Node {
int c;
int e;
} op[maxn];
int dp[maxn][maxn];
int main() {
// freopen("in.txt","r",stdin);
int n,m;
scanf("%d%d",&n,&m);
for(int i = 2; i <= n; i ++) {
int pre;
scanf("%d",&pre);
Vec[pre].push_back(i);
}
for(int i = 1; i <= n; i ++) scanf("%d",&op[i].c);
for(int i = 1; i <= n; i ++) scanf("%d",&op[i].e);
for(int i = n; i >= 1; i --) {
for(int k = 0; k < Vec[i].size(); k ++) {
int p = Vec[i][k];
for(int j = m; j >= 0; j --) {
for(int v = 0; v <= j; v ++){
if(dp[p][v] == 0) continue;
dp[i][j] = max(dp[i][j],dp[i][j - v] + dp[p][v]);
}
}
}
for(int j = m; j >= op[i].c; j --)
if(dp[i][j] < op[i].e) dp[i][j] = op[i].e;
}
printf("%d\n",dp[1][m]);
return 0;
}