SGU 149 树形DP Computer Network
2015-07-31 10:43
281 查看
这道题搜了一晚上的题解,外加自己想了半个早上,终于想得很透彻了。于是打算好好写一写这题题解,而且这种做法比网上大多数题解要简单而且代码也比较简洁。
首先要把题读懂,把输入读懂,这实际上是一颗有向树。第i(2≤i≤n)行的两个数u,d,其中u是i的父亲结点,d是距离。
第一遍DFS我们可以计算出以u为根的子树中,距离u最远的结点的距离d(u, 0)以及次远的距离d(u, 1)。而且,这两个不在u的同一棵子树中,如果u只有一个孩子,那么d(u, 1) = 0
第一遍DFS完以后,因为1是整棵树的跟,所以d(1, 0)就是距离1最远的距离。然后第二遍DFS,这次是用根的信息来更新它的子节点,此时d(u,0)d(u,1)的含义变为整棵树中距u最长和次长的距离。
如图:
代码君
首先要把题读懂,把输入读懂,这实际上是一颗有向树。第i(2≤i≤n)行的两个数u,d,其中u是i的父亲结点,d是距离。
第一遍DFS我们可以计算出以u为根的子树中,距离u最远的结点的距离d(u, 0)以及次远的距离d(u, 1)。而且,这两个不在u的同一棵子树中,如果u只有一个孩子,那么d(u, 1) = 0
第一遍DFS完以后,因为1是整棵树的跟,所以d(1, 0)就是距离1最远的距离。然后第二遍DFS,这次是用根的信息来更新它的子节点,此时d(u,0)d(u,1)的含义变为整棵树中距u最长和次长的距离。
如图:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 10000 + 10; vector<int> G[maxn], C[maxn]; int n; int d[maxn][2]; void dfs(int u) { for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; dfs(v); int t = d[v][0] + C[u][i]; if(t > d[u][0]) swap(t, d[u][0]); if(t > d[u][1]) swap(t, d[u][1]); } } void dfs2(int u) { for(int i = 0; i < G[u].size(); i++) { int v = G[u][i], t, w = C[u][i]; if(d[v][0] + w == d[u][0]) t = w + d[u][1]; else t = w + d[u][0]; if(t > d[v][0]) swap(t, d[v][0]); if(t > d[v][1]) swap(t, d[v][1]); dfs2(v); } } int main() { scanf("%d", &n); for(int u = 2; u <= n; u++) { int v, d; scanf("%d%d", &v, &d); G[v].push_back(u); C[v].push_back(d); } dfs(1); dfs2(1); for(int i = 1; i <= n; i++) printf("%d\n", d[i][0]); return 0; }
代码君
相关文章推荐
- 后台选择下拉框选项
- JS正则表达式验证数字非常全
- SQLServer2008把数据导出成可执行的sql脚本(R2版本)
- 打开人生珍贵的诗行,重新来读
- Android端如何获取手机当前的网络状态,比如wifi还是3G, 还是2G, 电信还是联通,还是移动
- HDU 1087 Super Jumping! Jumping! Jumping!(求绝对递增子序列的最大和)
- 黑马程序员——java中数组的定义与应用
- activity、fragment生命周期流程图
- JS正则表达式验证数字非常全
- mvn deploy返回400错误的几种可能
- LeetCode234——Palindrome Linked List,O(n) time and O(1) space
- 微信红包随机生成算法(PHP版)
- 使用httpclient对zip格式的响应数据解压
- Qt窗体关闭时,如何自动销毁窗体类对象
- FragmentPagerAdapter的工作流程(二)
- 判断app是否在前台运行
- 常用的宏定义
- Loadrunner常用15种的分析点
- Ansi,UTF8,Unicode,ASCII编码的区别
- String,StringBuffer,StringBuild的区别