HDU3586 Information Disturbing(树形dp+二分)
题意:
给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线。现要切断前线和司令 部的联系,每次切断边的费用不能超过上限limit,问切断所有前线与司令部联系所花费的总费用少于m时的最小limit。1<=n& lt;=1000,1<=m<=100万
思路:
dp[i]表示以i为根节点所花费的最小费用,二分找一下最小的limit就好了,ans初始化为-1,没有的话就自动输出-1了
inf不要开太大,dp加的时候会爆
/* *********************************************** Author :devil Created Time :2016/3/30 10:58:25 ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; #define inf 1e6+7 #define N 1010 int n,m; struct wq { int v,cost; }; vector<wq>eg[N]; int dp[N]; void init() { for(int i=1; i<=n; i++) eg[i].clear(); } void dfs(int u,int fa,int lim) { int leaf=1; dp[u]=0; for(int i=0; i<eg[u].size(); i++) { int to=eg[u][i].v; if(to==fa) continue; leaf=0; dfs(to,u,lim); if(eg[u][i].cost<=lim) dp[u]+=min(dp[to],eg[u][i].cost); else dp[u]+=dp[to]; } if(leaf) dp[u]=inf; } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)&&(n+m)) { int x,y,z,l=1,r=0,ans=-1; init(); for(int i=1; i<n; i++) { scanf("%d%d%d",&x,&y,&z); r=max(r,z); eg[x].push_back(wq{y,z}); eg[y].push_back(wq{x,z}); } while(l<=r) { int mid=(l+r)>>1; dfs(1,0,mid); if(dp[1]<=m) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); } return 0; }