HDU3586树形dp+二分查答案

思路很好想,二分可以的limit然后用树形dp更新看是否符合条件就好了,但是必须注意的一点是关于叶节点的赋值,因为叶子节点会被用于更新上面的节点,如果值一直是0的话就会挂掉,但如果值太大这道题会WA。。。。

#include<cstdio>
#include<algorithm>
#include<cstring>
const int MAXN=1005;
const int INF=1000010;
using namespace std;
struct Edge
{
    int nxt;
    int w;
    int to;
}edge[MAXN<<1];
int head[MAXN<<1];
int dp[MAXN];
int num;
void add(int from,int to,int w)
{
    edge[++num].nxt=head[from];
    edge[num].to=to;
    edge[num].w=w;
    head[from]=num;
}
void dfs(int u,int pre,int limit)
{
    bool flag=0; 
    dp[u]=0;
    for(int i=head[u];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v!=pre)
        {
            flag=1;
            dfs(v,u,limit);
            if(edge[i].w<=limit)
                dp[u]+=min(dp[v],edge[i].w);
            else
                dp[u]+=dp[v];
        }
    }   
    if(!flag)   
        dp[u]=INF;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)&&(n||m))
    {
        memset(head,0,sizeof(head));
        memset(edge,0,sizeof(edge));
        num=0;
        int wmax=-1;
        for(int i=1;i<=n-1;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
            if(w>wmax)
            {
                wmax=w;
            }
        }
        int ans=-1;
        int l=1;
        int r=wmax;
        while(l<=r)
        {
            int mid=(r+l)>>1;
            memset(dp,0,sizeof(dp));
            dfs(1,0,mid);        
            if(dp[1]<=m)
            {
                ans=mid;
                r=mid-1;
            }
            else 
            {
                l=mid+1;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Amuseir/article/details/80110439