[hdu3586]Information Disturbing树形dp+二分

题意:给出一棵带权无向树,以及给定节点1,总约束为$m$,找出切断与所有叶子节点联系每条边所需要的最小价值约束。

解题关键:二分答案,转化为判定性问题,然后用树形dp验证答案即可。

dp数组需要开到ll,如果用设inf的解法。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e6+7;
 5 const int inf=0x3f3f3f3f;
 6 struct edge{
 7     int to;
 8     int nxt;
 9     int w;
10 }e[maxn<<1];
11 ll cnt,head[1002];
12 ll dp[1002];
13 int n,m;
14 inline int read(){
15     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
16     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
17     if(k=='-')x=0-x;return x;
18 }
19 void add_edge(int u,int v,int w){
20     e[cnt].w=w;
21     e[cnt].to=v;
22     e[cnt].nxt=head[u];
23     head[u]=cnt++;
24 }
25 
26 void dfs(int u,int fa,int val){//还可以通过设立flag来确定叶子节点 
27     for(int i=head[u];i!=-1;i=e[i].nxt){
28         int v=e[i].to;
29         if(v==fa) continue;
30         dfs(v,u,val);
31         ll tmp=e[i].w>val?inf:e[i].w;
32         if(dp[v]==0) dp[u]+=tmp;
33         else dp[u]+=min(tmp,dp[v]);
34     }
35 }
36 
37 int erfen(int l,int r){
38     bool flag=false; 
39     while(l<r){
40         int mid=(l+r)>>1;
41         memset(dp,0,sizeof dp);
42         dfs(1,-1,mid);
43         if(dp[1]<=m) r=mid,flag=true;
44         else l=mid+1; 
45     }
46     if(flag)    return r;
47     else return -1;
48 }
49 
50 int main(){
51     while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
52         cnt=0;
53         memset(head,-1,sizeof head);
54         int a,b,c;
55         for(int i=0;i<n-1;i++){
56             a=read();b=read();c=read();
57             add_edge(a,b,c);
58             add_edge(b,a,c);
59         }
60         int ans=erfen(0,10001);
61         printf("%d
",ans);
62     } 
63 }
原文地址:https://www.cnblogs.com/elpsycongroo/p/7421124.html