公司层级結構是一棵樹(根節點1為Bill Hates)。每個程序員要么:
約束: 不能同時獲得和發放;一個人最多發放給一個下級。
目標: 最大化獲得獎金的總人數(每人1000美元)。
dp[u][0] : 節點 u 不與父節點匹配時,子樹內最大匹配數 dp[u][1] : 節點 u 與父節點匹配時,子樹內最大匹配數
dp[u][1] = Σ dp[v][0] (v 為 u 的所有孩子)Σ dp[v][0](等同於 dp[u][1])1 + dp[v][1] + Σ_{w≠v} dp[w][0]dp[u][0] = max( dp[u][1], max_{v} (1 + dp[v][1] - dp[v][0] + dp[u][1]) )void dfs_print(int u, int matched_with_parent) {
if (matched_with_parent) {
// u 與父匹配,所有孩子狀態為 0
for (v : children[u]) dfs_print(v, 0);
} else {
// 找出實現 dp[u][0] 的最優決策
int best_gain = 0, best_v = -1;
for (v : children[u]) {
int gain = 1 + dp[v][1] - dp[v][0];
if (gain > best_gain) best_gain = gain, best_v = v;
}
if (best_v == -1) {
// u 不匹配任何孩子
for (v : children[u]) dfs_print(v, 0);
} else {
// u 與 best_v 匹配
printf("%d ", best_v); // 輸出獲得獎金的孩子
dfs_print(best_v, 1); // best_v 與父匹配
for (v : children[u]) if (v != best_v)
dfs_print(v, 0);
}
}
}
輸入:
4
1 1 2 // 2,3的父是1;4的父是2
樹結構:1→{2,3}, 2→{4}
輸出:
2000
3 4
解釋:1發給2,3發給4(或2發給4,3不參與),共2人獲獎
vector children[N+1] ,避免邊數組