您的位置:首页 > 其它

SGU 149 Computer Network [树形DP]

2012-09-28 14:01 369 查看
  求树上的每个节点能到达的最远距离。

  先预处理出每个节点从叶子上来的最大距离和次大距离,并且记录最大距离是从哪个儿子上来的。

  对于每个节点,它能到的最大距离,要不就是走到自己的某个叶子,要不就是走到某个祖先节点然后转弯进入这个祖先的另一个儿子。向下DP,传递不经过这棵子树到该顶点的最大距离。

#include <string.h>
#include <stdio.h>
#include <algorithm>
#define MAXN 10001
#define INF 0x3f3f3f3f
using namespace std;

struct egde{
int v, w, n;
}e[MAXN*2];
int n, tu, tv, ans;
int first[MAXN], es;
void addedge(int u, int v, int w){
e[es].v = v, e[es].w = w;
e[es].n = first[u], first[u] = es++;
}
int mson[MAXN][2], mdis[MAXN][2], d[MAXN];
void dp1(int u, int f){
mdis[u][0] = mdis[u][1] = 0, mson[u][0] = mson[u][1] = -1;
for (int i = first[u]; i != -1; i = e[i].n) {
int v = e[i].v;
if (v == f) continue;
dp1(v, u);
if (mdis[v][0] + e[i].w > mdis[u][1]) mdis[u][1] = mdis[v][0] + e[i].w, mson[u][1] = v;
if (mdis[u][1]  > mdis[u][0]) swap(mdis[u][0], mdis[u][1]), swap(mson[u][0], mson[u][1]);
}
}
void dp2(int u, int f, int w){
d[u] = max(mdis[u][0], w);
for (int i = first[u] ; i != -1; i = e[i].n) {
int v = e[i].v;
if (v == f) continue;
int tmp = (mson[u][0]==v ? mdis[u][1]+e[i].w : mdis[u][0]+e[i].w);
dp2(v, u, max(w+e[i].w, tmp));
}
}
int main(){
scanf("%d", &n);
memset(first, -1, sizeof first); es = 0;
for (int i = 2; i <= n; i++) {
scanf("%d%d", &tu, &tv);
addedge(i, tu, tv);
addedge(tu, i, tv);
}
dp1(1, -1);
dp2(1, -1, 0);
for (int i = 1; i <= n; i++) printf("%d\n", d[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: