您的位置:首页 > 其它

*HDU 2196 - Computer(树形DP)

2015-07-31 21:52 363 查看
题目:

http://acm.hdu.edu.cn/showproblem.php?pid=2196

题意:

n个点,n-1条边,给出边权。求出每个节点最远的点的距离。

思路:

以1作为树根。


[插入]

如图,要得到节点2的最长距离,距离L1 是节点子树的最远距离,另一个距离L2 是图中的红色部分的最远距离+dis(2,1),结果为max(L1,L2)。

dp【v】【0】:记录节点v的子树的最远距离。此部分dfs1实现。

dp【v】【1】:记录v的父亲节点u 除了节点v的子树 的最远距离 + dis(u,v)。

                              实现方法为由父节点推到子节点。分为两种情况:

                              1. 如果v不是u的最长边上的点,则dp【v】【1】 = dis(u,v)+ max(dp【u】【0】, dp【u】【1】);

                              2. 如果v是u的最长边上的点,则 dp【v】【1】 = dis(u,v)+ max(second_long , dp【u】【1】);

注意答案是long long。

AC.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
typedef long long ll;
const int maxn = 1e4+10;
int n;

int head[maxn], tot;
struct Edge {
int to, next;
ll w;
}edge[2*maxn];
void addedge(int u, int v, ll w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}

ll dp[maxn][2];
bool vis[maxn];
ll dfs1(int u)
{
if(dp[u][0]) return dp[u][0];
vis[u] = 1;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
ll w = edge[i].w;
if(vis[v]) continue;

dp[u][0] = max(dp[u][0], dfs1(v) + w);
}
return dp[u][0];
}

void dfs2(int u)
{
vis[u] = 1;
ll max1 = 0, max2 = 0, w, tmp;
int v, v1, v2;

for(int i = head[u]; ~i; i = edge[i].next) {
v = edge[i].to; w = edge[i].w;
if(vis[v]) continue;

tmp = dp[v][0] + w;
if(tmp > max1) {
max2 = max1; max1 = tmp;
v1 = v;
}
else if(max1 == tmp || tmp > max2) max2 = tmp;
}

if(u != 1) {
tmp = dp[u][1];
v = -1;
if(tmp > max1) {
max2 = max1; max1 = tmp;
v1 = v;
}
else if(max1 == tmp || tmp > max2) max2 = tmp;

}

for(int i = head[u]; ~i; i = edge[i].next) {
v = edge[i].to;
w = edge[i].w;
if(vis[v]) continue;

if(v == v1) dp[v][1] = max2 + w;
else dp[v][1] = max1 + w;

dfs2(v);
}
}
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
memset(dp, 0, sizeof(dp));
}

int main()
{
//freopen("in", "r", stdin);
while(~scanf("%d", &n)) {
init();
for(int i = 2; i <= n; ++i) {
int u;
ll w;
scanf("%d%I64d", &u, &w);
addedge(u, i, w);
addedge(i, u, w);
}

memset(vis, 0, sizeof(vis));
dfs1(1);

memset(vis, 0, sizeof(vis));
dfs2(1);

for(int i = 1; i <= n; ++i) {
cout<<max(dp[i][0], dp[i][1])<<endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU