现在的位置: 首页 > 综合 > 正文

【树形DP】 hdu3586 Information Disturbing

2018年01月14日 ⁄ 综合 ⁄ 共 1301字 ⁄ 字号 评论关闭

 Information Disturbing

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3586

题意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线。现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所有前线与司令部联系所花费的总费用少于m时的最小limit。

题解:一般看出这题要树形DP不难,但是难在想到要二分。对于上限进行二分,然后通过树形DP进行判断。

代码:

#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 1010
#define inf (0xfffff)
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
int edge[MAX<<1];//表示第i条边的终点
int next[MAX<<1];//与第i条边同起点的下一条边的位置
int head[MAX<<1];//以i为起点的第一条边的储存位置
int cost[MAX<<1];
int dp[MAX];
void insert(int i,int a,int b,int c)//a起点,b终点
{
    edge[i]=b;
    next[i]=head[a];
    head[a]=i;
    cost[i]=c;
}
void dfs(int x,int pre,int maxx)
{
    bool flag=false;
    int total=0;
    for(int i=head[x]; i!=-1; i=next[i])
    {
        int k=edge[i];
        if(k!=pre)
        {
            flag=true;
            dfs(k,x,maxx);
            if(cost[i]>maxx) total+=dp[k];
            else total+=min(dp[k],cost[i]);
        }
    }
    if(flag) dp[x]=total;
    else     dp[x]=inf;
}
int main()
{
    int n,m;
    int a,b,c;
    for(; scanf("%d%d",&n,&m);)
    {
        if(n+m==0) break;
        int len=0,ans=inf;
        memset(head,-1,sizeof(head));
        memset(next,-1,sizeof(next));
        for(int i=1,j=1; i<n; ++i)
        {
            scanf("%d%d%d",&a,&b,&c);
            insert(j++,a,b,c);
            insert(j++,b,a,c);
            len=max(c,len);
        }
        int l=1,r=len,mid;
        for(; l<=r;)
        {
            memset(dp,0,sizeof(dp));
            mid=(l+r)>>1;
            dfs(1,-1,mid);
            if(dp[1]<=m)
            {
                ans=mid;
                r=mid-1;
            }
            else
                l=mid+1;
        }
        if(ans==inf) puts("-1");
        else         printf("%d\n",ans);
    }
    return 0;
}

来源:http://blog.csdn.net/ACM_Ted

抱歉!评论已关闭.