1. 程式人生 > >洛谷 P1352 沒有上司的舞會 解題報告 樹形DP

洛谷 P1352 沒有上司的舞會 解題報告 樹形DP

最值 周年慶 include -a void pre 代碼 style 結果

題目描述

某大學有N個職員,編號為1~N。他們之間有從屬關系,也就是說他們的關系就像一棵以校長為根的樹,父結點就是子結點的直接上司。現在有個周年慶宴會,宴會每邀請來一個職員都會增加一定的快樂指數Ri,但是呢,如果某個職員的上司來參加舞會了,那麽這個職員就無論如何也不肯來參加舞會了。所以,請你編程計算,邀請哪些職員可以使快樂指數最大,求最大的快樂指數。

輸入輸出格式

輸入格式:

第一行一個整數N。(1<=N<=6000)

接下來N行,第i+1行表示i號職員的快樂指數Ri。(-128<=Ri<=127)

接下來N-1行,每行輸入一對整數L,K。表示K是L的直接上司。

最後一行輸入0 0

輸出格式:

輸出最大的快樂指數。

輸入輸出樣例

輸入樣例#1: 復制
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
輸出樣例#1: 復制
5
題目已經強烈暗示了這題怎麽做,結構為樹,對每個人又要處理兩個抉擇,毫無疑問是爆搜(劃掉),樹形DP啦

先介紹一手樹形DP

簡單來說,樹形DP就是一個找兒子的DP,所有父親節點的狀態都由兒子更新,以此題為例,對於每個有下屬的人來說都有兩個選擇,自己不去,自己的下屬愛去不去;自己去,自己的下屬想去也不行,那麽轉移方程就出來了

設f[i][0/1]表示第i個人不去/去時的最大快樂值

f[i][0]=max(f[son][0],f[son][1])//下屬去不去中的最值

f[i][1]=max(f[son][0])+happy[i]//下屬想去也不行+自己的快樂值(這是下屬去不了自己就很快樂嗎。。。)

下面結合代碼講下

完整代碼

#include<bits/stdc++.h>
using namespace std;
const int MAXN=6005;
vector<int>son[MAXN];
int f[MAXN][2],a[MAXN],rt,n;
bool vis[MAXN];
void dfs(int rt)
{
    f[rt][0]=0;//不去的話不加上自己的快樂值
    f[rt][
1]=a[rt];//去的話加上自己的快樂值 for(int i=0;i<son[rt].size();i++)//找呀找呀找兒子 { int y=son[rt][i];//找到一個兒子 dfs(y);//遞歸向下,樹形DP是一個整合的過程,一切都是從最底層向上走的 f[rt][0]+=max(f[y][0],f[y][1]);//如果是第一次走到這一步說明已經到了底,之後每一次到說明到在一層一層往上走,套方程更新不去 f[rt][1]+=f[y][0];//套方程更新去的最大值 } } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i];//讀入快樂值 for(int i=1;i<=n;i++) { int x,y; cin>>x>>y; son[y].push_back(x);//讀入並連好父親到兒子的邊 vis[x]=1;//標記兒子 } for(int i=1;i<=n;i++)//找到沒有被標記的人,他就是校長,也就是總的根節點 if(!vis[i]) { rt=i;break; } dfs(rt);//從根節點開始DP cout<<max(f[rt][0],f[rt][1]); //所有的結果都會匯總到根節點中,輸出他去還是不去的最值即可 return 0; }

洛谷 P1352 沒有上司的舞會 解題報告 樹形DP