1. 程式人生 > >【樹狀DP】沒有上司的晚會

【樹狀DP】沒有上司的晚會

心累.jpg
新知識掌握的過程不會總是順利的。

Description 題目描述

Ural大學有N個職員,編號為1~N。他們有從屬關係,也就是說他們的關係就像一棵以校長為根的樹,父結點就是子結點的直接上司。每個職員有一個快樂指數。現在有個週年慶宴會,要求與會職員的快樂指數最大。但是,沒有職員願和直接上司一起與會。

Input

第一行一個整數N。(1<=N<=6000)
接下來N行,第i+1行表示i號職員的快樂指數Ri。(-128<=Ri<=127)
接下來N-1行,每行輸入一對整數L,K。表示K是L的直接上司。
最後一行輸入0,0。

Output

輸出最大的快樂指數。


思路

這****的儲存結構,令人抓狂
DP,用類似連結串列的東東存下職員們之間的關係,用了一大堆陣列。。。



已知,如果i職員被選去了晚會,那麼他的下屬一定不會去。
(但下屬的下屬是可以去的)
So,
我們就用f[i][1]表示他會去的最大快樂值,
f[i][0]表示他不會去的。
(此快樂值是隻考慮他和他的下屬的最優情況)
那麼f[i][1]=他的快樂指數+他的下屬不會去的快樂值。
f[i][0]=他所有屬下去或不去的快樂值(大的那個)

因為,i不去,他屬下也不一定會去,要是他屬下不去所能獲得的快樂值大於他屬下去的快樂值,那麼f[i][0]就加上他屬下不去的快樂值。
每個屬下都這樣判斷一遍。

超級亂的程式碼

待加註釋。。。

#include<cstdio>
#define ST 6001
using namespace std;
int max(int a,int b){   //求最大值
	if(a>b) return a;
	return b;
}
struct N{             
	int n,to,next;
} k[ST];
int head[ST],n,tot=0,a[ST],f[ST][ST]={0};
bool kkk[ST];
void add(int i,int j){
	k[++tot].n=i;
	k[tot].to=j;
	k[
tot].next=head[i]; head[i]=tot; kkk[j]=true; } void init(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<n;++i){ int j,l; scanf("%d%d",&j,&l); add(l,j); } } void cc(int now){ f[now][1]=a[now]; for(int i=head[now];i;i=k[i].next) { cc(k[i].to); f[now][1]=f[now][1]+f[k[i].to][0]; f[now][0]=max(f[k[i].to][1],f[k[i].to][0])+f[now][0]; } } int main(){ init(); int l; for(int i=1;i<=n;++i) if(kkk[i]==false) { l=i; break; } cc(l); if(f[l][1]>f[l][0]) printf("%d",f[l][1]); else printf("%d",f[l][0]); }