1. 程式人生 > 其它 >vue 上傳外掛

vue 上傳外掛

題目連結:https://www.acwing.com/problem/content/287/

題目描述

Ural 大學有 N 名職員,編號為 1∼N。
他們的關係就像一棵以校長為根的樹,父節點就是子節點的直接上司。
每個職員有一個快樂指數,用整數 Hi 給出,其中 1≤i≤N。
現在要召開一場週年慶宴會,不過,沒有職員願意和直接上司一起參會。
在滿足這個條件的前提下,主辦方希望邀請一部分職員參會,使得所有參會職員的快樂指數總和最大,求這個最大值。

輸入描述

第一行一個整數 N。
接下來 N 行,第 i 行表示 i 號職員的快樂指數 Hi。
接下來 N−1 行,每行輸入一對整數 L,K,表示 K 是 L 的直接上司。

輸出描述

輸出最大的快樂指數。
1≤N≤6000
−128≤Hi≤127

示例

輸入

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5

輸出

5

分析

約定

我們記每個人的歡樂度為happy[i]。

狀態表示

職員間的從屬關係可以用一棵樹來表示,每一位員工的父節點為其直接上司。
我們用f[i][0]表示第i個節點代表的員工不參加舞會的情況下,以第i個節點為根節點的子樹參與舞會情況的最大歡樂度和。
用f[i][1]表示第i個節點代表的員工參加舞會的情況下,以第i個節點為根節點的子樹參與舞會情況的最大歡樂度和。

狀態計算

由題意得父節點與子節點得關係如下:

  • 若父節點參與舞會,則兒子節點均不能參與舞會
  • 若父節點不參與舞會,則兒子節點參與舞會沒有限制,參不參與都行

因此,我們可以得到狀態轉移方程:
f[i][0] = max(f[j1][0],f[j1][1]) + max(f[j2][0],f[j2][1]) + ··· (j1,j2,···為其兒子節點)
f[i][1] = happy[i] + f[j1][0] + f[j2][0] + ···· (j1,j2,···為其兒子節點)

各狀態的求解採用DFS實現,類似記憶化搜尋。

AC程式碼


#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 6010;
int n;
int happy[N];
int h[N], e[2 * N], ne[2 * N], idx;		//鄰接表儲存樹
int f[N][2];
int has_father[N];

void add(int x, int y)
{
	e[idx] = y;
	ne[idx] = h[x];
	h[x] = idx;
	idx++;
}

void dfs(int u)
{
	f[u][1] = happy[u];
	for (int i = h[u]; i != -1; i = ne[i])
	{
		dfs(e[i]);
		f[u][0] += max(f[e[i]][0], f[e[i]][1]);
		f[u][1] += f[e[i]][0];
	}
}

int main()
{
	memset(h, -1, sizeof(h));

	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> happy[i];
	for (int i = 0; i < n - 1; i++)
	{
		int x, y;
		cin >> x >> y;
		add(y, x);
		has_father[x] = y;
	}

	int root = 1;
	while (has_father[root])		//確定根節點
		root = has_father[root];
	dfs(root);

	cout << max(f[root][0], f[root][1]) << endl;
	return 0;
}