码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 2196 树形dp

时间:2015-07-20 11:03:19      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:dp

题意: 给你n太台电脑 及 相邻之间的 距离 让你求出 每台电脑的离它最远的电脑的离;

思路:树形dp,题意给出一棵树,求离每个节点最远的点的距离, 两种情况1,以该节点s作为根节点的子树中的离该节点最长距离x。2,其父树中离该节点的最长距离y。答案就是max(x, y);

需要注意的是:父树中的最长距离有可能经过s点, 这时候就要选父树中次长的路径(求第一种时顺便求出)

ps:建图时是双向边  不明白在纸上画图走一遍样例

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#define N 10005<<1
#define INF 10000000
#define LL long long
#define eps 10E-9
#define mem(a)  memset(a,0,sizeof(a))
#define mem1(a)  memset(a,-1,sizeof(a))
#define w(a)   while(a)
#define s(a)   scanf("%d",&a)
#define ss(a,b)   scanf("%d%d",&a,&b)
#define sss(a,b,c)   scanf("%d%d%d",&a,&b,&c)
using namespace std;
int dp[N][3];//设dp[i][1]、dp[i][0]第i节点的子树方向最长距离、次长距离 ,设dp[i][2]为第i节点的父树方向最长距离
int fnext[N];//与第i条边同起点的下条边的位置
int head[N];//以i为起点的第一条边的位置
int edge[N];//第i条边的终点
int cost[N];//第i条边的长度
int vis[N];//优化 用不用都行
void add(int i, int a, int b, int c){
     edge[i] = b;
     fnext[i] = head[a];
     head[a] = i;
     cost[i] = c;
}
void tree_dp1(int a, int b){
     for(int i=head[a]; i!=-1; i=fnext[i]){
        int k = edge[i];
        if( k!= b){
            tree_dp1(k, a);
            if(dp[a][0] < cost[i] + dp[k][0]){
                    dp[a][1] = dp[a][0];
                    dp[a][0] = cost[i] + dp[k][0];
               }
            else if(dp[a][1] < cost[i] + dp[k][0]) dp[a][1] = cost[i] +  dp[k][0];
        }
     }
}
void tree_dp2(int a, int b){
     int len = 0;
     for(int i=head[a]; i!=-1; i=fnext[i]){
        if(edge[i] == b){
           len = cost[i]; break;
        }
     }
     if(b != -1 && !vis[a]){
        dp[a][2] = dp[b][2];
        if(dp[a][0] + len == dp[b][0] && dp[b][1] > dp[a][2]) dp[a][2] = dp[b][1];
        if(dp[a][0] + len != dp[b][0] && dp[b][0] > dp[a][2]) dp[a][2] = dp[b][0];
        dp[a][2] += len ;
        vis[a] = 1;
     }
     for(int i=head[a]; i!=-1; i=fnext[i]){
        if(edge[i] !=b ) tree_dp2(edge[i], a);
     }
}
int main(){
   int n, j, i, a, b;
   w(~s(n)){
         mem(vis);
         mem(dp);
         mem1(fnext);
         mem1(head);
         for(i=2, j=1; i<=n; i++){
            ss(a, b);
            add(j++, i, a, b);
            add(j++, a, i, b);
         }
         tree_dp1(1, -1);//求子树最长距离
         tree_dp2(1, -1);//求父树最长距离
         for(int i=1; i<=n; i++)    printf("%d\n",max(dp[i][0],dp[i][2]));
   }
   return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 2196 树形dp

标签:dp

原文地址:http://blog.csdn.net/bigsungod/article/details/46963643

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!