【树形DP+二分】HDU3586 Information Disturbing

来源:互联网 发布:编译原理代码优化 编辑:程序博客网 时间:2024/06/05 17:57

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

I think

    题目大意:在一棵树上删去一些边使得所有叶子节点不能到达根节点,并使所有被删去的边权值和小于等于m,求被删边中最长边的最小值。
    树形DP+二分
    要发现题给的两个条件从某种程度上是矛盾的,当两条边权是3一条边权是4的边等效时,前者删去边lim=3,但删去边权值和是6,后者删去边lim=4>3,但删去边权值和=4<6。
    因此我们可以二分lim跑树形DP。
    用f[i]表示删去以i节点为根节点的子树的所有叶节点的删去边权最小值,叶节点f[i]初始化为inf,inf注意不开过大防溢出。

Code

#include<cstdio>#include<climits>#include<cstring>#include<algorithm>using namespace std;const int sm = 1e3+20;const int inf = 1e6+20;int n,m,s,l,r,lim,maxn,f[sm],hd[sm];bool flag;struct edge{    int to,nxt,len;}e[sm*2];int Max(int x,int y){return x>y?x:y;}int Min(int x,int y){return x<y?x:y;}void add(int f,int t,int l) {    e[++s].to=t;e[s].len=l;e[s].nxt=hd[f];hd[f]=s;}char ch;void dfs(int x,int fa){    bool yes=0;f[x]=0;    for(int i=hd[x];i;i=e[i].nxt){        if(e[i].to==fa)continue;        yes=1;dfs(e[i].to,x);        int minn=inf;        if(e[i].len<=lim)minn=Min(minn,e[i].len);        minn=Min(minn,f[e[i].to]);        f[x]+=minn;    }    if(!yes)f[x]=inf;}int main() {    while(scanf("%d%d",&n,&m)!=EOF) {           if(!n&&!m)break;        s=0;l=1;r=1;        memset(hd,0,sizeof(hd));        for(int i=1,x,y,z;i<n;++i) {            scanf("%d%d%d",&x,&y,&z);            add(x,y,z);add(y,x,z);            r=Max(r,z);        }        while(l+1<r) {            lim=(l+r)>>1;dfs(1,-1);            if(f[1]<=m)r=lim;else l=lim+1;        }        lim=l;dfs(1,-1);        if(f[1]>m) {            lim=r;dfs(1,-1);            if(f[1]>m){printf("-1\n");continue;}        }        printf("%d\n",lim);    }    return 0;}
阅读全文
0 0
原创粉丝点击