依旧。。不会。。
二分,因为题中说要找到代价和小于m并且输出那个代价和中最大的边,就要用到二分了。对每个边判断其实否小于二分中mid的值(也就是limit)
状态转移方程:if(w[j与其孩子的边的代价]<=limit)dp[j]+=min(dp[j的孩子],w[连接j与其孩子的边的代价])
else dp[j]+=dp[j的孩子];
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define Max 2000
using namespace std;
int n,m,dp[2020],pos,list[1010];
struct P{
int u,v,next,w;
}point[2020];
void add(int fa,int son,int wi){
point[pos].u=fa;
point[pos].v=son;
point[pos].w=wi;
point[pos].next=list[fa];
list[fa]=pos++;
}
void dfs(int son,int fa,int limit){
bool flag=false;
int now=list[son];
dp[son]=0;
while(now!=-1){
if(point[now].v==fa){
now=point[now].next;
continue;
}
dfs(point[now].v,son,limit);
flag=true;
if(point[now].w<=limit){
dp[son]+=min(dp[point[now].v],point[now].w);
}
else{
dp[son]+=dp[point[now].v];
}
now=point[now].next;
}
if(flag==0){
dp[son]=Max;
}
return ;
}
int main(){
while(scanf("%d%d",&n,&m)&&(n&&m)){
pos=0;
memset(list,-1,sizeof(list));
int l=1,r=0,mid;
for(int i=1;i<n;i++){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
add(a,b,w);
add(b,a,w);
if(r<w)r=w;
}
// printf("! l=%d r=%d\n",l,r);
int ans=Max;
while(l<=r){
mid=(r+l)/2;
dfs(1,-1,mid);
if(dp[1]<=m){
r=mid-1;
ans=mid;
}
else{
l=mid+1;
}
// printf("! l=%d r=%d dp[1]=%d\n",l,r,dp[1]);
}
if(ans!=Max){
printf("%d\n",ans);
}
else{
printf("-1\n");
}
}
return 0;
}
一开始二分判断为l<r
但是wa了,后来发现,这个条件会少判断一次l==r 所以加一次就好了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define Max 1000010
using namespace std;
int n,m,dp[2020],pos,list[1010];
struct P{
int u,v,next,w;
}point[2020];
void add(int fa,int son,int wi){
point[pos].u=fa;
point[pos].v=son;
point[pos].w=wi;
point[pos].next=list[fa];
list[fa]=pos++;
}
void dfs(int son,int fa,int limit){
bool flag=false;
int now=list[son];
dp[son]=0;
while(now!=-1){
if(point[now].v==fa){
now=point[now].next;
continue;
}
dfs(point[now].v,son,limit);
flag=true;
if(point[now].w<=limit){
dp[son]+=min(dp[point[now].v],point[now].w);
}
else{
dp[son]+=dp[point[now].v];
}
now=point[now].next;
}
if(flag==0){
dp[son]=Max;
}
return ;
}
int main(){
while(scanf("%d%d",&n,&m)&&(n&&m)){
pos=0;
memset(list,-1,sizeof(list));
int l=1,r=0,mid,ans=Max;
for(int i=1;i<n;i++){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
add(a,b,w);
add(b,a,w);if(w>r)r=w;
}
printf("! l=%d r=%d\n",l,r);
while(l<r){
mid=(r+l)/2;
dfs(1,-1,mid);
if(dp[1]<=m){
r=mid;ans=mid;
}
else{
l=mid+1;
}
printf("! l=%d r=%d dp[1]=%d\n",l,r,dp[1]);
}
dfs(1,-1,(r+l)/2);
if(dp[1]<=m)ans=(r+l)/2;
if(ans!=Max){
printf("%d\n",ans);
}
else{
printf("-1\n");
}
}
return 0;
}