链接:点击打开链接
题意:根节点为1的一棵树,删除一些边使叶子节点都不能到达根节点,并且边权和不能大于M,使删除边的最大值最小,并输出
代码:
#include <queue> #include <vector> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> using namespace std; const int INF=1100000; struct node{ int to,cost; }; int n,m,dp[1005],used[1005]; vector<node> G[1005]; void dfs(int s,int cnt){ int i,j,tmp; used[s]=1; for(i=0;i<G[s].size();i++){ tmp=G[s][i].to; if(!used[tmp]){ dfs(tmp,cnt); if(G[s][i].cost>cnt) //大于限制直接取子节点的值 dp[s]+=dp[tmp]; else dp[s]+=min(dp[tmp],G[s][i].cost); } } } int judge(int mid){ int i; for(i=1;i<=n;i++){ //叶子节点为INF,INF不要过大否则加的时候后 if(G[i].size()==1&&i!=1) //超上限 dp[i]=INF; else dp[i]=0; } memset(used,0,sizeof(used)); dfs(1,mid); if(dp[1]<=m) return 1; return 0; } int main(){ int i,j,l,r,u,v,w,ans,mid; while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){ r=0; for(i=0;i<=n;i++) G[i].clear(); for(i=0;i<n-1;i++){ scanf("%d%d%d",&u,&v,&w); G[u].push_back((node){v,w}); G[v].push_back((node){u,w}); r=max(r,w); //二分上限 } l=1,ans=-1; //最大值最小因此进行二分 while(l<=r){ mid=(l+r)>>1; if(judge(mid)){ ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); } return 0; }