Hdu Information Disturbing
Description
- In the battlefield , an effective way to defeat enemies is to break their
communication system.
The information department told you that there are n
enemy soldiers and their network which have n-1 communication routes can cover
all of their soldiers. Information can exchange between any two soldiers by the
communication routes. The number 1 soldier is the total commander and other
soldiers who have only one neighbour is the frontline soldier.
Your boss zzn
ordered you to cut off some routes to make any frontline soldiers in the network
cannot reflect the information they collect from the battlefield to the total
commander( number 1 soldier).
There is a kind of device who can choose some
routes to cut off . But the cost (w) of any route you choose to cut off can’t be
more than the device’s upper limit power. And the sum of the cost can’t be more
than the device’s life m.
Now please minimize the upper limit power of your
device to finish your task.
Input
- The input consists of several test cases.
The first line of each test case
contains 2 integers: n(n<=1000)m(m<=1000000).
Each of the following N-1
lines is of the form:
ai bi wi
It means there’s one route from ai to
bi(undirected) and it takes wi cost to cut off the route with the
device.
(1<=ai,bi<=n,1<=wi<=1000)
The input ends with n=m=0.
Output
- Each case should output one integer, the minimal possible upper limit power of
your device to finish your task.
If there is no way to finish the task,
output -1.
Sample Input
5 5
1 3 2
1 4 3
3 5 5
4 2 6
0 0
Sample Output
3
题解:
- 首先二分上限。每次得到一个总价钱sum。如果sum<=m,下调上限。否则上调上限
- check函数里是一个树形dp。
- 设dp(i)表示以i为根节点时,其通讯爆炸时的最小花费。
- 那么对于一个点,它与叶子的通讯不是它儿子断掉了,就是它自己手动断掉了。
- 所以转移:dp(i) = \(\sum{min(dp(son), e[i].dis)}\)
//顶尖了:inf太大会WA!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define maxn 1005
#define inf 1100000
using namespace std;
struct E {int next, to, dis;} e[maxn * 2];
int n, m, num;
int h[maxn], dp[maxn];
int read()
{
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x *= f;
}
void add(int u, int v, int w)
{
e[++num].next = h[u];
e[num].to = v;
e[num].dis = w;
h[u] = num;
}
void dfs(int x, int fat, int val)
{
for(int i = h[x]; i != 0; i = e[i].next)
if(e[i].to != fat)
dfs(e[i].to, x, val);
for(int i = h[x]; i != 0; i = e[i].next)
if(e[i].dis > val) dp[x] += dp[e[i].to];
else dp[x] += min(dp[e[i].to], e[i].dis);
}
int check(int val)
{
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)
if(!e[h[i]].next && i != 1) dp[i] = inf;
dfs(1, 0, val);
return dp[1] <= m;
}
int main()
{
while(scanf("%d%d", &n, &m) == 2)
{
if(!n && !m) break;
num = 0;
memset(h, 0, sizeof(h));
for(int i = 1; i < n; i++)
{
int u = read(), v = read(), w = read();
add(u, v, w), add(v, u, w);
}
int l = 0, r = 0x3f3f3f3f, ans = -1;
while(l <= r)
{
int mid = (l + r) >> 1;
if(check(mid)) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%d\n", ans);
}
return 0;
}