题意:给出一棵树,和每条边的cost值,设置一个界限,要求切断所有叶子结点,切断的边的cost不能超过界限值,并且切断的边的总和不能超过m,求出这个最小界限值。
思路:二分枚举最小界限值,用树状DP求出在这个限制下的最小花费是否小于m。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
#include <vector>
#include <cmath>
#include <stack>
using namespace std;
#define ll long long
#define int64 __int64
#define M 100005
#define N 1005
#define inf 1000010
#define mod 1000000007
struct node
{
int ev , cost;
};
int n , m , MAX , dp[N];
vector<node> son[N];
void Dfs(int s , int fa , int k)
{
int i , up = son[s].size() , fg = 0;
dp[s] = 0;
for (i = 0 ; i < up ; i++)
{
int v = son[s][i].ev;
int cost = son[s][i].cost;
if (v == fa)continue;
fg = 1;
Dfs(v,s,k);
if (cost <= k)dp[s] += min(dp[v],cost);
else dp[s] += dp[v];
}
if(!fg)dp[s] = inf;
}
int Solve()
{
int l = 0 , r = MAX , mid , ret = -1;
while (l <= r)
{
mid = (l+r)>>1;
Dfs(1,0,mid);
if (dp[1] <= m)
{
ret = mid;
r = mid-1;
}
else
l = mid+1;
}
return ret;
}
int main()
{
while (scanf("%d%d",&n,&m) , m+n)
{
int i;
MAX = 0;
for (i = 1 ; i < n ; i++)
{
int s , e , w;
scanf("%d%d%d",&s,&e,&w);
node temp;
temp.ev = e;
temp.cost = w;
son[s].push_back(temp);
temp.ev = s;
son[e].push_back(temp);
MAX = max(MAX,w);
}
printf("%d\n",Solve());
for (i = 1 ; i <= n ; i++)son[i].clear();
}
return 0;
}