hdu 2196 树形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;

}

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

时间: 2024-08-24 00:20:51

hdu 2196 树形dp的相关文章

Computer HDU - 2196(树形dp)

题目要求:求树上每个点能到达的最远距离 dp[u][0]:u的子树下u的最远距离是多少 dp[u][1]:u的子树次远距离是多少 dp[u][2]:u的父亲能走的最远距离是多少 dp[0] [1]dfs处理即可 如果vi不是u最长距离经过的节点,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1]) 如果vi是u最长距离经过的节点,那么不能选择f[u][0],因为这保存的就是最长距离,要选择u次大距离 #include<bits/stdc++.h> #defin

hdu 4123 树形DP+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=4123 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses,

hdu 1250 树形DP

Anniversary party Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-27) Description There is going to be a party to celebrate the 80-th Anniversary of the Ural St

hdu 4276(树形dp)

题意:带权树上有起点终点每个点上有宝藏,一个人只有T分钟要从起点到重点,问你最多能收集多少宝藏. 思路:树形dp,首先判断能不能走到终点,然后把路径上的边权变为0时间减去所有边权.dp[v][j]表示从v出发回到v话费j分钟最多能收集到的宝藏. dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]); 被G++卡了好长时间,换成c++就过了. 代码如下: 1 #include <stdio.h> 2 #include <string.h

hdu 5148 树形dp+分组背包问题

http://acm.hdu.edu.cn/showproblem.php?pid=5148 Problem Description Long long ago,there is a knight called JayYe.He lives in a small country.This country is made up of n cities connected by n-1 roads(that means it's a tree).The king wants to reward Ja

HDU 1520 树形dp裸题

1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b using nam

hdu 3586 树形dp+二分

题目大意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵 树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线.现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所 有前线与司令部联系所花费的总费用少于m时的最小limit.1<=n<=1000,1<=m<=100万 题目要问的是最小的最大限制,必然二分答案 然后对于每一个值,树形DP判定是否可行 dp[i]表示要切断以i为根的其它所有子树的最小代价. 其中设定叶子结点的代价为无穷大

HDU 1561 树形DP入门

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6011    Accepted Submission(s): 3555 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物

hdu 1561 树形dp

又一道树形dp,发现其实树形dp长得都挺像的. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF = -9999999; 7 const int N = 201; 8 int dp[N][N]; 9 int head[N]; 10 int value[N]; 11 int n, m, e; 12 13 void i