题目链接
之前写了纯的树形DP,现在用一下二分来进行优化
我二分中设定的答案为限制,就是最多能剪去价值为mid的枝,并且所有的子枝之和也要不大于mid,然后判断最后的dp[1]是否“<=M”即可。
这里有一个细节,INF不要开到0x3f3f3f3f(或者1e9),会WA,我改了下INF就过了。
完整代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
const int maxN=1005;
const int INF=1e6+7;
//const int INF=0x3f3f3f3f;
int N, M, cnt, head[maxN];
int dp[maxN];
struct Eddge
{
int to, nex, val;
Eddge(int a=0, int b=-1, int c=0):to(a), nex(b), val(c) {}
}edge[maxN];
void addEddge(int u, int v, int val)
{
edge[cnt]=Eddge(v, head[u], val);
head[u]=cnt++;
}
void dfs(int u, int pre, int mid)
{
if(head[u]==-1) { dp[u]=INF; return; }
for(int tmp=head[u]; tmp!=-1; tmp=edge[tmp].nex)
{
int v=edge[tmp].to, val=edge[tmp].val;
if(v==pre) continue;
dfs(v, u, mid);
dp[u]+=min(dp[v], val>mid?INF:val);
}
}
bool check(int mid)
{
for(int i=1; i<=N; i++) dp[i]=0;
dfs(1, 0, mid);
return dp[1]<=M?true:false;
}
int main()
{
while(scanf("%d%d", &N, &M) && (N | M))
{
cnt=0; memset(head, -1, sizeof(head));
for(int i=1; i<N; i++)
{
int e1, e2, e3;
scanf("%d%d%d", &e1, &e2, &e3);
addEddge(e1, e2, e3);
}
int l=0, r=M, ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) { r=mid-1; ans=mid; }
else l=mid+1;
}
printf("%d\n", ans);
}
return 0;
}