[HDU3586]Information Disturbing(DP + 二分)

传送门

题意:给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超过上限limit,问在保证总费用<=m下的最小的limit

二分答案,再 DP,看看最终结果是否小于 m

——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 1001
 5 #define max(x, y) ((x) > (y) ? (x) : (y))
 6 
 7 int n, m, cnt, ans;
 8 int a[N], sum[N], head[N], to[N << 1], val[N << 1], next[N << 1];
 9 bool vis[N];
10 
11 inline int read()
12 {
13     int x = 0, f = 1;
14     char ch = getchar();
15     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
16     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
17     return x * f;
18 }
19 
20 inline void add(int x, int y, int z)
21 {
22     to[cnt] = y;
23     val[cnt] = z;
24     next[cnt] = head[x];
25     head[x] = cnt++;
26 }
27 
28 inline void dfs(int u, int x)
29 {
30     int i, v;
31     vis[u] = 1;
32     for(i = head[u]; i ^ -1; i = next[i])
33     {
34         v = to[i];
35         if(!vis[v])
36         {
37             dfs(v, x);
38             if(val[i] <= x)
39             {
40                 if(val[i] < sum[v]) sum[u] += val[i];
41                 else sum[u] += sum[v];
42             }
43             else sum[u] += sum[v];
44         }
45     }
46 }
47 
48 inline bool check(int x)
49 {
50     memset(vis, 0, sizeof(vis));
51     memset(sum, 0, sizeof(sum));
52     for(int i = 2; i <= n; i++)
53         if(a[i] == 1)
54             sum[i] = m + 1;
55     dfs(1, x);
56     return sum[1] <= m;
57 }
58 
59 int main()
60 {
61     int i, x, y, z, mid;
62     while(1)
63     {
64         cnt = 0;
65         n = read();
66         m = read();
67         if(!n && !m) break;
68         memset(a, 0, sizeof(a));
69         memset(head, -1, sizeof(head));
70         for(i = 1; i < n; i++)
71         {
72             a[x = read()]++;
73             a[y = read()]++;
74             z = read();
75             add(x, y, z);
76             add(y, x, z);
77         }
78         x = 1, y = m, ans = -1;
79         while(x <= y)
80         {
81             mid = (x + y) >> 1;
82             if(check(mid)) ans = mid, y = mid - 1;
83             else x = mid + 1;
84         }
85         printf("%d
", ans);
86     }
87     return 0;
88 }
View Code
原文地址:https://www.cnblogs.com/zhenghaotian/p/7044648.html