hdu3586 Information Disturbing

【题意】

给定一棵以1为根节点的有n个点的有边权的无向树,要求切断所有叶子节点和根节点的联系,要求边权和小于等于m,问最大的边权值最小为多少

【分析】

首先很显然,我们需要二分答案转换为判定性的问题,然后看通过<=mid的边权的边能否是总的边权小于等于m还满足条件

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1005;
int head[maxn],n,m;
struct edge
{
    int to,nxt,v;
}e[maxn<<1];
int cnt;
void add(int x,int y,int z)
{
    e[++cnt].to=y; e[cnt].nxt=head[x]; e[cnt].v=z; head[x]=cnt;
}
const int inf=0x3f3f3f3f;
ll f[maxn];
void dfs(int u,int fa,int lim)
{
    int flag=0; f[u]=0;
    for(int i=head[u];i;i=e[i].nxt)
    {
        int to=e[i].to;
        if(to==fa) continue;
        flag++;
        dfs(to,u,lim);
        if(e[i].v>lim) f[u]+=f[to];
        else f[u]+=min(f[to],1ll*e[i].v);
    }
    if(!flag) f[u]=inf;
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    while(scanf("%d%d",&n,&m) && n+m)
    {  
        int x,y,z,maxi=0;
        memset(head,0,sizeof(head)); cnt=0;
        for(int i=2;i<=n;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z); add(y,x,z);
            maxi=max(maxi,z);
        }
        // printf("%d\n",maxi);
        int l=1,r=maxi,ans=-1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            dfs(1,0,mid);
           // for(int i=1;i<=n;i++) printf("%d ",f[i]);
            if(f[1]<=m) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

这里这个f开long long 的原因是inf加了很多次会爆int,开始wa了好多次 qwq

 

posted @ 2021-09-05 18:05  andyc_03  阅读(18)  评论(0编辑  收藏  举报