1. 程式人生 > >沒有上司的舞會(樹形dp裸題)

沒有上司的舞會(樹形dp裸題)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 2e5;
bool used[MAXN];
int n,a,b,num[MAXN],s,firs[MAXN],ans,nex[MAXN],dp[MAXN][2],cnt = 0;
struct zt
{
    int f,t;
}road[MAXN];
void build(int f,int t)
{
    road[++cnt] = (zt){f,t};
    nex[cnt] = firs[f];
    firs[f] = cnt;
}
int
dfs(int x,int d) //表示x 去(d == 1)還是不去(d == 0)。 { int ans = 0; for(int i = firs[x];i != -1; i = nex[i]) { int v = road[i].t; if(!dp[v][0]) dp[v][0] = dfs(v,0); // 記憶化,表示該狀態下dp[編號][去與否]的最大值 if(!dp[v][1]) dp[v][1] = dfs(v,1); if(d) ans += dp[v][0
]; //上司去。 else ans += max(dp[v][0],dp[v][1]);//上司不去,若其下有更優解他也可能不去。 } if(d) return ans + num[x];//x 若去要加上他自己。 return ans; } int main() { scanf("%d",&n); for(int i = 1;i <= n; i++) scanf("%d",&num[i]),firs[i] = -1; for(int i = 1;i < n; i++) { scanf
("%d%d",&a,&b); build(b,a); // 建立上下級關係的圖 used[a] = 1; } scanf("%d%d",&a,&b); for(int i = 1;i <= n;i ++) if(!used[i]) { s = i; //找到大boss(根節點)。 break; } ans = max(dfs(s,0),dfs(s,1)); // 分別計算大boss去還是不去。 printf("%d",ans); }