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]
![](https://img-blog.csdn.net/20160721013410185)
若不在,则使用deep[u][0](也就是最大距离)+|<u,v>|(u到v的距离)来更新deep[v]。
![](https://img-blog.csdn.net/20160721013404798)
通过deep[u][0] == deep[v][0]+|<u,v>|来判断v是否在路径上。最后输出所有的deep[i][0]。
题目大意:给出从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; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法