Luogu P1352 沒有上司的舞會 題解
Luogu P1352 沒有上司的舞會 [傳送門]
題目描述
某大學有N個職員,編號為1~N。他們之間有從屬關系,也就是說他們的關系就像一棵以校長為根的樹,父結點就是子結點的直接上司。現在有個周年慶宴會,
宴會每邀請來一個職員都會增加一定的快樂指數Ri,但是呢,如果某個職員的上司來參加舞會了,那麽這個職員就無論如何也不肯來參加舞會了。
所以,請你編程計算,邀請哪些職員可以使快樂指數最大,求最大的快樂指數。
輸入輸出格式
輸入格式:
第一行一個整數N。(1<=N<=6000)
接下來N行,第i+1行表示i號職員的快樂指數Ri。(-128<=Ri<=127)
接下來N-1行,每行輸入一對整數L,K。表示K是L的直接上司。
最後一行輸入0 0
輸出格式:
輸出最大的快樂指數。
輸入輸出樣例
輸入樣例:7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
輸出樣例:
5
這道題...怎麽說呢...
似曾相識...嗯對似曾相識(何止是似曾相識...簡直跟戰略遊戲一模一樣嘛,只是它把f[u][0]和f[u][1]換了下位置罷了...)
大概就是老樣子
用f[u][0]表示在節點u不妨置人,用f[u][1]表示在節點u要放置人;
我們知道當節點u要放置人時,它的子節點v必須不放置人才能讓快樂指數(背對疾風吧!hasaki)達到max;
同理,節點u不放置人的時候,它的子節點v可以選擇放置人或者不放置人都可以,所以我們取其中的最大值;
(圖在這裏↓)
那麽,狀態轉移方程就出來了: f[u][0]+=max(f[v][0],f[v][1]);(此時u不放置人)
或 f[u][1]+=f[u][0];
狀態轉移方程出來了就簡單了吖
但實際上還有一個問題,大家應該都發現了這個根節點的不定的問題,也就是說這棵樹的根是不確定的,該怎麽辦呢?
答案巨型九頭簡單
那就是
不!管!它!
這是為什麽呢???
其實我們不妨設置1就為根節點,建邊的時候雙向建邊就行了,最後在dp模塊裏判定一下讓u==v的時候為無效狀態就ok。
(圖就變成了這樣子↓)
所以一眼就看出來了
都是隔一個節點放置一個人嘛
所以沒什麽影響啊
那麽,代碼如下:
#include<bits/stdc++.h>
#define maxn 100000
#define maxm 10000
using namespace std;
int N;
int head[maxm],k=0;
int R[maxm];
int f[maxn][2];
struct node{
int u,v,nxt;
}e[maxn];
void adde(int u,int v){
e[k].v=v;
e[k].nxt=head[u];
head[u]=k++;
}
void init(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
}
void readdata(){
memset(head,-1,sizeof(head));
int u,v;
scanf("%d",&N);
for(int i=1;i<=N;i++){
scanf("%d",&R[i]);
}
for(int i=1;i<N;i++){
scanf("%d%d",&u,&v);
adde(u,v);
adde(v,u);
}
}
void dp(int u,int fa){
f[u][0]=0;f[u][1]=R[u];
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].v;
if (v==fa) continue;
dp(v,u);
f[u][1]+=f[v][0];
f[u][0]+=max(f[v][0],f[v][1]);
}
}
void work(){
dp(1,0);
printf("%d",max(f[1][0],f[1][1]));
}
int main(){
//init();
readdata();
work();
return 0;
}
總的來說還是比較簡單(反正比選課簡單到哪去了(手動不爽))
Luogu P1352 沒有上司的舞會 題解