1. 程式人生 > >[hdu3586]Information Disturbing樹形dp+二分

[hdu3586]Information Disturbing樹形dp+二分

long style using 葉子 flag its != 定性 pac

題意:給出一棵帶權無向樹,以及給定節點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\n",ans); 62 } 63 }

[hdu3586]Information Disturbing樹形dp+二分