zoukankan      html  css  js  c++  java
  • hdu 3586 树形dp+二分

    题目大意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵 树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线。现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所 有前线与司令部联系所花费的总费用少于m时的最小limit。1<=n<=1000,1<=m<=100万

    链接:点我

    题目要问的是最小的最大限制,必然二分答案
    然后对于每一个值,树形DP判定是否可行
    dp[i]表示要切断以i为根的其它所有子树的最小代价。
    其中设定叶子结点的代价为无穷大
    那么对于某一个非叶子结点,要切断一棵子树就有两种选择,切断以孩子为根的子树或者切断根与孩子的边。
    如果根与孩子的边大于限制,那就取无穷大。
    最后判断1号结点的总花费是否小于等于m
    注意:无穷大不要取太大,否则会连续相加溢出

    Sample Input
    5 5
    1 3 2
    1 4 3
    3 5 5
    4 2 6
    0 0
     
    Sample Output
    3

     注意没结果要输出-1

    INF大小要注意搞好

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<map>
     8 using namespace std;
     9 #define MOD 1000000007
    10 const int INF=1000010;
    11 const double eps=1e-5;
    12 typedef long long ll;
    13 #define cl(a) memset(a,0,sizeof(a))
    14 #define ts printf("*****
    ");
    15 const int MAXN=1005;
    16 int n,m,tt,tot=0,head[MAXN],dp[MAXN];
    17 int maxw;
    18 struct edge
    19 {
    20     int to,next;
    21     int w;
    22 }edge[MAXN*2];
    23 void addedge(int a,int b,int w)
    24 {
    25     edge[tot].to=a;
    26     edge[tot].next=head[b];
    27     edge[tot].w=w;
    28     head[b]=tot++;
    29 }
    30 void init()
    31 {
    32     memset(head,-1,sizeof(head));
    33     tot=0;
    34     maxw=0;
    35 }
    36 void dfs(int u,int pre,int limit)
    37 {
    38     int flag=0;
    39     for(int i=head[u];i!=-1;i=edge[i].next)
    40     {
    41         int v=edge[i].to;
    42         if(v==pre)  continue;
    43         flag=1;
    44         dfs(v,u,limit);
    45         if(edge[i].w<=limit)    dp[u]+=min(dp[v],edge[i].w);    //切子树,或者切与子树相连的边
    46         else    dp[u]+=dp[v];   //只能切断子树
    47     }
    48     if(!flag)   dp[u]=INF;  //叶子不能切哦
    49 }
    50 int main()
    51 {
    52     int i,j,k;
    53     #ifndef ONLINE_JUDGE
    54     freopen("1.in","r",stdin);
    55     #endif
    56     while(scanf("%d%d",&n,&m)!=EOF)
    57     {
    58         init();
    59         if(n==0&&m==0)  break;
    60         int u,v,w;
    61         for(i=1;i<n;i++)
    62         {
    63             scanf("%d%d%d",&u,&v,&w);
    64             addedge(u,v,w);
    65             addedge(v,u,w);
    66             if(maxw<w)  maxw=w;
    67         }
    68         int l=1,r=maxw;
    69         int ans=-1;
    70         while(l<=r)
    71         {
    72             cl(dp);
    73             int mid=(l+r)>>1;
    74             dfs(1,-1,mid);
    75             if(dp[1]<=m)
    76             {
    77                 ans=mid;
    78                 r=mid-1;
    79             }
    80             else    l=mid+1;
    81         }
    82         printf("%d
    ",ans);
    83     }
    84 }
  • 相关阅读:
    hihoCoder #1176 : 欧拉路·一 (简单)
    228 Summary Ranges 汇总区间
    227 Basic Calculator II 基本计算器II
    226 Invert Binary Tree 翻转二叉树
    225 Implement Stack using Queues 队列实现栈
    224 Basic Calculator 基本计算器
    223 Rectangle Area 矩形面积
    222 Count Complete Tree Nodes 完全二叉树的节点个数
    221 Maximal Square 最大正方形
    220 Contains Duplicate III 存在重复 III
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4330318.html
Copyright © 2011-2022 走看看