树形DP+二分(Information Disturbing HDU3586)
题意:给出一颗数,1结点代表司令部,叶子节点代表前线,边全值代表花费,然后需要在某些边放置一些炸弹,炸弹的能量不能小于该边的费用,且炸掉的总费用不能超过m问炸弹能力最小多少,
分析dfs+二分,二分枚举下限,费用小于mid的可以炸掉,不能通过,且没有点可以到达叶子节点
#include"stdio.h" #include"string.h" #include"queue" #include"vector" #define M 10000 #define inf 1000000 using namespace std; int t,n,head[M],degree[M],dis[M],sum; struct node { int u,v,w,next; }edge[M*2]; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[t].u=u; edge[t].v=v; edge[t].w=w; edge[t].next=head[u]; head[u]=t++; } int dfs(int u,int f,int mid) { if(degree[u]==1&&u!=1) return 1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(edge[i].w<=mid) sum+=edge[i].w; if(v==f||edge[i].w<=mid)continue; if(dfs(v,u,mid)) return 1; } return 0; } int main() { int m,i; while(scanf("%d%d",&n,&m),m||n) { init(); memset(degree,0,sizeof(degree)); for(i=1;i<n;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); degree[a]++; degree[b]++; } int l=0,r=1000,mid,ans=-1; while(l<=r) { mid=(l+r)/2; sum=0; if(dfs(1,1,mid)) { l=mid+1; } else { r=mid-1; if(sum<=m) ans=mid; } } printf("%d\n",ans); } return 0; }