HDU 2196 Computer [树形dp]

来源:互联网 发布:java 字符串排列组合 编辑:程序博客网 时间:2024/05/16 12:24

题干

走你

题解

/***比较经典的树形dp*跑两次深搜,都是从根1开始搜索,第一次深搜获得最大子树,*第二次深搜是在第一次深搜的基础上,进行dp操作,获得最终结果*一个结点最终的结果,可能来自于这个结点的父亲,也可能来自这个结点的儿子,而儿子在第一次深搜*的时候就得出来了,所以应该从上往下搜出来自父亲的最大权值来决定是否再次更新*/#include<cstdio>#include<vector>#include<cstring>#include<algorithm>#define max(x,y) (x) > (y) ? (x) : (y)#define min(x,y) (x) < (y) ? (x) : (y)using namespace std;struct Edge{    int u;    int val;    Edge(int _u, int _val):u(_u),val(_val){}};vector<Edge>vec[10010];int dp[10010];int dfs(int root){    if(dp[root] != -1)return dp[root];    int size = vec[root].size();    int ans = -1;    for(int i=0; i<size; i++){       int res = dfs(vec[root][i].u);       if(res == -1){           res = 0;           dp[vec[root][i].u] = 0;       }       int val = vec[root][i].val;       ans = max(ans, res + val);    }    return dp[root] = ans;}int result[10010];void trees(int root, int length){    int size = vec[root].size();    result[root] = max(result[root], length);    result[root] = max(result[root], dp[root]);    int u, val, first = 0, second = -1, mymax;    //找出第一大的值    for(int i=0;i<size;i++){        u = vec[root][i].u;        val = dp[u] + vec[root][i].val;        if(val > first)first = val;    }    bool flag = false;    //找出第二大的值,因为第二大的值可能和第一大的值相同,所以,用flag标记出来    for(int i=0;i<size;i++){        u = vec[root][i].u;        val = dp[u] + vec[root][i].val;        if(!flag && first == val){            flag = true;continue;        }        if(first != val && val > second)second =  val;        else if(first == val && flag && val > second)second = val;    }    for(int i=0;i<size;i++){       u = vec[root][i].u;       val = vec[root][i].val;       //检查这个最大值是不是来自这个子树       if(first == dp[u] + vec[root][i].val){         mymax = second;       }else{         mymax = first;       }       //深搜       trees(u, max(mymax + val, length + val));    }}int main(){    //freopen("in.txt","r",stdin);    int N,u,val;    while(~scanf("%d",&N)){        vec[0].clear();        vec[1].clear();        for(int i=2;i<=N;i++){            vec[i].clear();            scanf("%d%d",&u,&val);            vec[u].push_back(Edge(i,val));        }        memset(dp, -1, sizeof(dp));        int a,b;        dfs(1);        memset(result, -1, sizeof(result));        trees(1, 0);        for(int i=1;i<=N;i++){           printf("%d\n",result[i]);        }    }    return 0;}
0 0
原创粉丝点击