(简单) 树形dp HDU 3586 Information Disturbing

来源:互联网 发布:手机扒谱软件 编辑:程序博客网 时间:2024/05/26 09:55

Information Disturbing

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 1236    Accepted Submission(s): 451


Problem 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 51 3 21 4 33 5 54 2 60 0
 

Sample Output
3
 

Author
alpc86
 

Source
2010 ACM-ICPC Multi-University Training Contest(15)——Host by NUDT
 

题意:给出一颗树,树边附有权值,要求删除一些边,使得任意两个叶子不能通过根节点访问对方,要求删除的边的权值和不大于m,求出符合上述要求的情况下,删除的边之中的最大权值在所有可行方案中最小
思路:我们用二分查找来确定upper limit power(后面简称为limit) ,在一个limit下,进行dp,求出满足要求的情况的最小权值和,看这个权值和是否超过了m 如果超过了说明limit 太小,limit要更大, 如果没有超过,说明这个limit是可行的的,于是我们尝试找更小的limit。
在dp中,我们用dp[i]表示以i为根的子树,删除掉一些边使得这颗子树的叶子不能相互通过1交流的最小权值和,那么在状态转移的时候就有  dp[i] += max(dp[son],w);  其中w是i到son之间的树边的权值,因为我们删除这条树边也能满足son子树的叶子不能通过1节点互相交流,所以我们取更小的。然后如果w超过了limit那么我们把w置为无穷大,表示这条边不能删。如果一个dp[i]的值为无穷大代表什么呢?就是这颗子树,在limit删除边下不能达到要求,这样是我们把w置为无穷大的原因。



代码:
#include<cstdio>
#include<algorithm>
#include<sstream>
#include<set>
#include<iostream>
#include<map>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 1000+10;
const int inf = 2000000;
#define LL long long

LL dp[maxn];
int ptr,n,m;
int ww[maxn];

struct Node
{
int v;
int w;
Node *next;
}*first[maxn],edge[maxn*2];

void add(int x,int y,int c)
{
edge[++ptr].v = y;
edge[ptr].w = c;
edge[ptr].next = first[x];
first[x] = &edge[ptr];
}

void dfs(int x,int fa,int lim)
{
Node *p = first[x];
bool leaf = true;
while (p)
{
int v = p->v;
LL w = p->w;
if (v!=fa)
{
leaf = false;
dfs(v,x,lim);
dp[x] += min(dp[v], w > lim ? inf : w);
}
p = p->next;
}
if (leaf)
dp[x] = inf;
}

void init()
{
ptr = 0;
memset(first,0,sizeof(first));
}

int main()
{
while (scanf("%d%d",&n,&m) , n || m)
{
init();
for (int i = 0 ; i < n-1 ; ++i)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
add(x,y,c);
add(y,x,c);
ww[i] = c;
}
int left = 0 , right = n-1;
int mid = (left+right)>>1;
int ans = inf;
sort(ww,ww+n-1);
while (left<=right)
{
memset(dp,0,sizeof(dp));
dfs(1,-1,ww[mid]);
if (dp[1]>m)
left = mid+1;
else 
{
ans = ww[mid];
right = mid-1;
}
mid = (left+right)>>1;
}
if (ans==inf)
printf("-1\n");
else 
printf("%d\n",ans);
}
}
0 0
原创粉丝点击