题意:给出一棵带权无向树,以及给定节点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 }