zoukankan      html  css  js  c++  java
  • hdu3586 Information Disturbing 树形DP+二分

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3586

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

    思路:很容易想到DP,定义dp[root]表示以root为根节点的子树失去与其叶子节点的链接的最小花费,那么如果其与孩子的边权小于limit,则dp[root]+=min(dp[son],w)(son为root的孩子,w为相连的边的权值),否则的话,dp[root]+=dp[son];

    那么怎样确定limit值呢,由于问题是求使总花费不超过m的最小的limit值,当然就是二分答案了,确定limit的值的下限为1,上限为最大的边值,然后对于limit进行二分查找,如果最后求的总的花费值小于等于m,则往前找,否则就往后找。

    代码如下:

     1 #include<cstdlib>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 #define MAX 1010
     7 #define INF 1000010
     8 class node
     9 {
    10     public:
    11     int to;
    12     int w;
    13     int next;
    14 };
    15 node edge[2*MAX];
    16 int head[MAX];
    17 int n,m;
    18 int tol;
    19 int dp[MAX];
    20 int vis[MAX];
    21 void init()
    22 {
    23    tol=0;
    24    memset(head,-1,sizeof(head));
    25 }
    26 void Build_Tree(int u,int v,int w)
    27 {
    28     edge[tol].to=v;
    29     edge[tol].w=w;
    30     edge[tol].next=head[u];
    31     head[u]=tol++;
    32 }
    33 int low,high,mid;
    34 void dfs(int root,int pre)
    35 {
    36   vis[root]=1;
    37   int flag=0;
    38   for(int i=head[root];i!=-1;i=edge[i].next)
    39     {
    40        if(vis[edge[i].to]) continue;
    41        flag=1;
    42        int cost=edge[i].w;
    43        int son=edge[i].to;
    44        dfs(son,root);
    45        if(cost<=mid) dp[root]+=min(dp[son],cost);
    46        else dp[root]+=dp[son];
    47     }
    48     if(flag==0) dp[root]=INF;
    49 }
    50 int main()
    51 {
    52         while(scanf("%d%d",&n,&m)!=EOF)
    53         {
    54            init();
    55            if(n==0&&m==0) break;
    56            low=1;high=0;
    57   
    58           for(int i=1;i<n;i++)
    59           {
    60               int u,v,w;
    61               scanf("%d%d%d",&u,&v,&w);
    62               if(high<w) high=w; 
    63               Build_Tree(u,v,w);
    64               Build_Tree(v,u,w);
    65           }
    66           int ans=-1;
    67         while(low<=high)
    68         {
    69           memset(dp,0,sizeof(dp));
    70           memset(vis,0,sizeof(vis));
    71           mid=(low+high)/2;
    72           dfs(1,-1);
    73           if(dp[1]>m) low=mid+1;
    74           else {high=mid-1;ans=mid;}
    75         }
    76         cout<<ans<<endl;
    77        }
    78        return 0;
    79 }
    View Code
  • 相关阅读:
    delphi 调用百度地图api
    Delphi XE5 for android 图片缩放和拖动处理
    利用FMX控件的MakeScreenshot过程实现WAIT效果
    老外写的在桌面添加快捷方式(DELPHI XE5 ANDROID)
    第01组 Alpha冲刺(5/6)
    2019 SDN上机第4次作业
    2019 SDN阅读作业
    第01组 Alpha冲刺(4/6)
    第01组 Alpha冲刺(3/6)
    第01组 Alpha冲刺(2/6)
  • 原文地址:https://www.cnblogs.com/xiaozhuyang/p/hdu3586.html
Copyright © 2011-2022 走看看