1. 程式人生 > 其它 >HDU 3586 Information Disturbing【二分 + 樹形DP】

HDU 3586 Information Disturbing【二分 + 樹形DP】

技術標籤:# 動態規劃——樹形DP

Information Disturbing

題意: 一棵有邊權的樹,要求刪除一些邊,使得根節點1和所有的葉子節點斷開聯絡。要求是:

  • 刪除的邊的權值和必須小於m
  • 刪除的邊權的最大值儘可能小

題解: 兩個條件看似是不能統一的,總和必須小於m,但是最大權值又要儘可能小。

舉個栗子,如果DFS過程中追求權值和最小,那麼將會得到答案6,但這個卻不是最小的最大權。
在這裡插入圖片描述

對於這種,就應該去列舉最大權,然後DFS驗證是否正確。當然,應該二分列舉。

#include<bits/stdc++.h>
using namespace std;
const int maxn =
1100; int n, m; int dp[maxn]; int cnt, head[maxn]; struct edge { int v, w, next; } e[maxn << 1]; void add (int u, int v, int w) { e[++cnt] = {v, w, head[u]}; head[u] = cnt; e[++cnt] = {u, w, head[v]}; head[v] = cnt; } int DFS (int u, int fa, int lim) { dp[u] = 0; for (int i = head[u]; i; i =
e[i].next) { int v = e[i].v, w = e[i].w; if (v == fa) continue; int c = (w > lim ? m + 1 : w); dp[u] += min(DFS(v, u, lim), c); } return dp[u] ? dp[u] : m + 1; } void run () { cnt = 0; memset(head, 0, sizeof head); for (int i = 1, u, v, w; i < n; ++i) { scanf("%d%d%d", &
u, &v, &w); add(u, v, w); } int ans = -1; int l = 0, r = m; while (l <= r) { int mid = (l + r) >> 1; if (DFS(1, 0, mid) <= m) ans = mid, r = mid - 1; else l = mid + 1; } printf("%d\n", ans); } int main () { while (~scanf("%d%d", &n, &m) && (n + m)) run(); return 0; }