程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 3586 Information Disturbing(二分+數形DP)

HDU 3586 Information Disturbing(二分+數形DP)

編輯:C++入門知識

題目:給出n個士兵,其中1號為指揮官,關系為樹狀結構,葉子為先鋒,現在要在總花費小於m的情況切斷所有的先鋒與指揮官的聯系,問最大的限制最小為多少
http://acm.hdu.edu.cn/showproblem.php?pid=3586
題目要問的是最小的最大限制,必然二分答案
然後對於每一個值,樹形DP判定是否可行
dp[i]表示要切斷以i為根的其它所有子樹的最小代價。
其中設定葉子結點的代價為無窮大
那麼對於某一個非葉子結點,要切斷一棵子樹就有兩種選擇,切斷以孩子為根的子樹或者切斷根與孩子的邊。
如果根與孩子的邊大於限制,那就取無窮大。
最後判斷1號結點的總花費是否小於等於m
注意:無窮大不要取太大,否則會連續相加溢出
[cpp] 
#include<iostream> 
#include<fstream> 
#include<iomanip> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
#include<cstdlib> 
#include<cmath> 
#include<set> 
#include<map> 
#include<queue> 
#include<stack> 
#include<string> 
#include<vector> 
#include<ctime> 
#include<sstream> 
#include<cassert> 
#define LL long long 
#define eps 1e-7 
#define zero(a) fabs(a)<eps 
#define inf 1<<20 
#define N 100005 
#define pi acos(-1.0) 
#define pb(a) push_back(a) 
#define lson step<<1 
#define rson step<<1|1 
using namespace std; 
struct Node{ 
    int v,w,next; 
}edge[100005]; 
int start[1005],tot; 
int n,m,dp[1005]; 
void addedge(int u,int v,int w){ 
    edge[tot].v=v;edge[tot].w=w; 
    edge[tot].next=start[u]; 
    start[u]=tot++; 

void _addedge(int u,int v,int w){ 
    addedge(u,v,w); 
    addedge(v,u,w); 

void dfs(int u,int limit,int pre){ 
    bool flag=false; 
    for(int i=start[u];i!=-1;i=edge[i].next){ 
        int v=edge[i].v,w=edge[i].w; 
        if(v==pre) continue; 
        flag=true; 
        dfs(v,limit,u); 
        dp[u]+=min(dp[v],w>limit?inf:w); 
    } 
    if(!flag) dp[u]=inf; 

bool check(int limit){ 
    memset(dp,0,sizeof(dp)); 
    dfs(1,limit,-1); 
   // cout<<limit<<" "<<dp[1]<<" "<<dp[2]<<" "<<dp[3]<<" "<<dp[4]<<endl; 
    if(dp[1]>m) return false; 
    return true; 

int main(){ 
    while(scanf("%d%d",&n,&m)!=EOF&&n+m){ 
        tot=0;memset(start,-1,sizeof(start)); 
        for(int i=1;i<n;i++){ 
            int u,v,w; 
            scanf("%d%d%d",&u,&v,&w); 
            _addedge(u,v,w); 
        } 
        int low=0,high=m,mid,ok=0,ans=-1; 
        while(low<=high){ 
            mid=(low+high)/2; 
            if(check(mid)) {ans=mid;high=mid-1;} 
            else low=mid+1; 
        } 
        printf("%d\n",ans); 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved