Information Disturbing
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3586
解题思路:
题目大意:
给你n个敌方据点,1为司令部,其他点各有一条边相连构成一棵树,每条边都有一个权值val表示破坏这条边的费用,叶子节点为前
线。现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所有前线与司令部联系所花费的总费用少于m时的
最小limit。
算法思想:
容易看出这题要用树形DP不难,但是难在想到要二分。对于上限进行二分,然后通过树形DP进行判断。
坑点:INF设置不能太大。。。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define INF 1000005;
using namespace std;
const int N = 1005;
struct node{
int v,val;
node(){}
node(int _v,int _val){
v = _v; val = _val;
}
};
vector<node> edge[N];
int n,m;
int dp[N];
void dfs(int u,int fa,int lim){
int flag = 0; //标记是不是叶子结点
dp[u] = 0;
int len = edge[u].size();
for(int i = 0; i < len; ++i){
int v = edge[u][i].v;
if(v != fa){
flag = 1;
dfs(v,u,lim);
if(edge[u][i].val <= lim)
dp[u] += min(dp[v],edge[u][i].val);
else
dp[u] += dp[v];
}
}
if(!flag) //叶子结点无穷大
dp[u] = INF;
}
int main(){
while(scanf("%d%d",&n,&m),n+m){
for(int i = 0; i <= n; ++i)
edge[i].clear();
int MAX = 0;
int u,v,val;
for(int i = 1; i < n; ++i){
scanf("%d%d%d",&u,&v,&val);
edge[u].push_back(node(v,val));
edge[v].push_back(node(u,val));
if(val > MAX)
MAX = val;
}
int l = 1,r = MAX,ans = -1;
while(l <= r){
int mid = (l+r)>>1;
dfs(1,-1,mid);
if(dp[1] <= m){
ans = mid;
r = mid-1;
}else
l = mid+1;
}
printf("%d\n",ans);
}
return 0;
}