您的位置:首页 > 其它

SGU 149 Computer Network(树形DP)

2016-07-21 01:36 441 查看
题目链接:点击打开链接

题目大意:给出从2~n号节点的父节点与其和父节点的距离,输出每个节点到树中节点的最大距离。

解题思路:第一遍DFS,用deep[i][0]记录节点i到其子节点的最大距离,deep[i][1]保存次大距离。

第二遍DFS,deep[i][0]的意义变成了节点i到树中节点的最大距离,deep[i][1]为次大距离。由于根节点1的deep[1][0]表示的就是距离树中节点的最大距离,所以可以从1开始向下变遍历,使用父节点的deep来更新当前节点的deep。具体更新的规则是:若子节点v在父节点u到最远节点的路径上,就用deep[u][1](也就是次大距离)+|<u,v>|(u到v的距离)来更新deep[v]



若不在,则使用deep[u][0](也就是最大距离)+|<u,v>|(u到v的距离)来更新deep[v]。



通过deep[u][0] == deep[v][0]+|<u,v>|来判断v是否在路径上。最后输出所有的deep[i][0]。

#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 50;
const int MOD = 1e9 + 7;

int n, dis[MAXN], deep[MAXN][2];
struct Edge
{
int u, v, val, nxt;
}E[MAXN];
int Head[MAXN], erear;

void edge_init()
{
erear = 0;
memset(Head, -1, sizeof(Head));
}

void edge_add(int u, int v, int val)
{
E[erear].u = u;
E[erear].v = v;
E[erear].val = val;
E[erear].nxt = Head[u];
Head[u] = erear++;
}

int dfs1(int u, int f)
{
for (int i = Head[u]; ~i; i = E[i].nxt)
{
int v = E[i].v;
if (v == f)
continue;
int tmpdeep = dfs1(v, u) + E[i].val;
if (tmpdeep > deep[u][0])
swap(tmpdeep, deep[u][0]);
if (tmpdeep > deep[u][1])
swap(tmpdeep, deep[u][1]);
}
return deep[u][0];
}

void dfs2(int u, int f)
{
for (int i = Head[u]; ~i; i = E[i].nxt)
{
int v = E[i].v;
if (v == f)
continue;
int tmpdeep;
if (deep[u][0] == deep[v][0] + E[i].val)
tmpdeep = deep[u][1] + E[i].val;
else
tmpdeep = deep[u][0] + E[i].val;
if (tmpdeep > deep[v][0])
swap(tmpdeep, deep[v][0]);
if (tmpdeep > deep[v][1])
swap(tmpdeep, deep[v][1]);
dfs2(v, u);
}
}

int main()
{
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while (~scanf("%d", &n))
{
edge_init();
for (int i = 2; i <= n; i++)
{
int v, val;
scanf("%d%d", &v, &val);
edge_add(v, i, val);
edge_add(i, v, val);
}
memset(deep, 0, sizeof(deep));
dfs1(1, -1);
dfs2(1, -1);
for (int i = 1; i <= n; i++)
printf("%d\n", deep[i][0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 算法 dp