HDU 3586 Information Disturbing (树形dp+二分)

来源:互联网 发布:一元淘宝网怎么找 编辑:程序博客网 时间:2024/05/25 16:40

题意:给你n个结点,m,然后有n-1行数据,每行三个数据a,b,c,表示切断a,b之间的联系是c。结点1是指挥部,叶子结点为前线,在花费不超过的m的基础上,求切断的点中花费最大的最小值。


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


题解思路:不难看出这是一道树形dp,但是这样确定这个极限值,我们可以通过二分枚举,因为两个结点中花费最大为1000,所以我们最多枚举10次,这个复杂度还是可以接受的。状态转移方程:dp[i] += min(cost[i][son], dp[son])或者dp[i] += dp[son], i表示结点i,cost[i][son]表示i结点与孩纸结点之间的花费。前一个方程为cost[i][son]的值小为我们枚举范围中的最大值,第二个自然为大于的情况,因此在状态转移时需要判断一个两者的大小关系。

附上ac代码:

#include <algorithm>#include <iostream>#include <cstring>#include <string>#include <queue>#include <stack>#include <list>#include <map>#include <set>#define Forn_m(n,m) for(int i = n; i <= m; i++)#define ForN_m(n,m) for(int i = n; i < m; i++) #define MAX 1005#define INF 1e6+50using namespace std;struct Edge{    int v, lenght;};int n, m;int dp[MAX];bool vis[MAX];vector <Edge> vec[MAX];void dfs(int father,int num,int root, int limit){    bool flag = false;    int nu = vec[root].size();    vis[root] = true;    ForN_m(0, nu)    {        if (!vis[vec[root][i].v])        {            dfs(root,i,vec[root][i].v, limit);            flag = true;            if (vec[root][i].lenght <= limit)                dp[root] += min(dp[vec[root][i].v], vec[root][i].lenght);            else                dp[root] += dp[vec[root][i].v];        }    }    if (!flag)        if (vec[father][num].lenght <= limit)            dp[root] = vec[father][num].lenght;        else            dp[root] = INF;}void dichotomia(int left, int right){    memset(vis, 0, sizeof(vis));    memset(dp, 0, sizeof(dp));    int temp = (left + right) >> 1;    dfs(-1,-1,1,temp);    if (left == right)        if (dp[1] <= m)            printf("%d\n", left);        else            printf("-1\n");    else if (dp[1] <= m)        dichotomia(left, temp);    else        dichotomia(temp + 1, right);}int main(){    Edge temp;    int u, t;    while (scanf("%d%d", &n, &m) && (n != 0 || m != 0))    {        Forn_m(1, n)            vec[i].clear();        memset(vis, 0, sizeof(vis));        ForN_m(1, n)        {            scanf("%d%d%d", &u, &temp.v, &temp.lenght);            vec[u].push_back(temp);            t = temp.v;            temp.v = u;            vec[t].push_back(temp);        }        dichotomia(1, 1000);    }    return 0;}


0 0