题目描述 Description

小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上。有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力。已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力

输入描述 Input Description

第一行一个n,接下来n-1行每一行有三个整数u, v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。

第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u, v 表示两只虫子所在的节点

输出描述 Output Description

一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。

样例输入 Sample Input

  1. 3
  2. 1 0 1
  3. 2 0 1
  4. 3
  5. 1 0
  6. 2 0
  7. 1 2

样例输出 Sample Output

  1. 1
  2. 1
  3. 2

数据范围及提示 Data Size & Hint

1<=n<=50000,1<=m<=75000,0<=c<=1000

题解和代码

这道题显然是一道LCA的题目,我们可以跑一遍树上倍增。

  1. #include <iostream>
  2. #include <deque>
  3. #include <vector>
  4. #include <cmath>
  5. using namespace std;
  6. int n, m;
  7. struct edge_type
  8. {
  9. int u, v, c, nextu, nextv;
  10. };
  11. edge_type edge[50005];
  12. const int root = 0;
  13. int hu[50005], hv[50005], fa[50005], fac[50005], deep[50005], f[50005][30], maxdeep = 0, fsum[50005][30];
  14. int maxi;
  15. bool vis[50005];
  16. vector<int> son[50005];
  17. deque<int> q;
  18. void bfs_build_tree(const int root)
  19. {
  20. q.push_back(root);
  21. for (int i = 0; i <= n; ++i)
  22. {
  23. vis[i] = false;
  24. }
  25. vis[root] = true;
  26. deep[root] = 1;
  27. int now;
  28. while (!q.empty())
  29. {
  30. now = q.front();
  31. if (maxdeep < deep[now])
  32. maxdeep = deep[now];
  33. q.pop_front();
  34. int i = hu[now];
  35. while (i)
  36. {
  37. if (!vis[edge[i].v])
  38. {
  39. q.push_back(edge[i].v);
  40. vis[edge[i].v] = true;
  41. fa[edge[i].v] = now;
  42. fac[edge[i].v] = edge[i].c;
  43. son[now].push_back(edge[i].v);
  44. deep[edge[i].v] = deep[now] + 1;
  45. }
  46. i = edge[i].nextu;
  47. }
  48. i = hv[now];
  49. while (i)
  50. {
  51. if (!vis[edge[i].u])
  52. {
  53. q.push_back(edge[i].u);
  54. vis[edge[i].u] = true;
  55. fa[edge[i].u] = now;
  56. fac[edge[i].u] = edge[i].c;
  57. son[now].push_back(edge[i].u);
  58. deep[edge[i].u] = deep[now] + 1;
  59. }
  60. i = edge[i].nextv;
  61. }
  62. }
  63. }
  64. void get_f()
  65. {
  66. maxi = log2(double(maxdeep)-0.5);
  67. for (int j = 0; j < n; ++j)
  68. {
  69. f[j][0] = fa[j];
  70. fsum[j][0] = fac[j];
  71. for (int i = 1; i <= 30; ++i)
  72. fsum[j][i] = f[j][i] = -1;
  73. }
  74. fsum[0][0] = f[0][0] = -1;
  75. for (int i = 1; i <= maxi; ++i)
  76. for (int j = 1; j < n; ++j)
  77. if ((1 << i) < deep[j])
  78. {
  79. f[j][i] = f[f[j][i-1]][i-1];
  80. fsum[j][i] = fsum[j][i-1] + fsum[f[j][i-1]][i-1];
  81. }
  82. }
  83. int g(int x, int y)
  84. {
  85. int ret = 0, a = x, b = y;
  86. while (deep[b] > deep[a])
  87. {
  88. for (int i = maxi; i >= 0; --i)
  89. if (deep[f[b][i]] > deep[a])
  90. {
  91. ret += fsum[b][i];
  92. b = f[b][i];
  93. }
  94. if (deep[fa[b]] == deep[a])
  95. {
  96. ret += fac[b];
  97. b = fa[b];
  98. }
  99. }
  100. while (deep[a] > deep[b])
  101. {
  102. for (int i = maxi; i >= 0; --i)
  103. if (deep[f[a][i]] > deep[b])
  104. {
  105. ret += fsum[a][i];
  106. a = f[a][i];
  107. }
  108. if (deep[fa[a]] == deep[b])
  109. {
  110. ret += fac[a];
  111. a = fa[a];
  112. }
  113. }
  114. while (a != b)
  115. {
  116. for (int i = maxi; i >= 0; --i)
  117. if (f[a][i] != f[b][i])
  118. {
  119. ret += (fsum[a][i] + fsum[b][i]);
  120. a = f[a][i];
  121. b = f[b][i];
  122. }
  123. if (fa[a] == fa[b])
  124. {
  125. ret += (fac[a] + fac[b]);
  126. a = fa[a];
  127. b = fa[b];
  128. }
  129. }
  130. return ret;
  131. }
  132. int main()
  133. {
  134. cin >> n;
  135. int u, v, c;
  136. for (int i = 1; i < n; ++i)
  137. {
  138. cin >> u >> v >> c;
  139. edge[i].u = u;
  140. edge[i].v = v;
  141. edge[i].c = c;
  142. edge[i].nextu = hu[u];
  143. edge[i].nextv = hv[v];
  144. hu[u] = i;
  145. hv[v] = i;
  146. }
  147. bfs_build_tree(root);
  148. get_f();
  149. cin >> m;
  150. int a, b;
  151. for (int i = 0; i < m; ++i)
  152. {
  153. cin >> a >> b;
  154. cout << g(a, b) << endl;
  155. }
  156. }

Codevs 2370 小机房的树 LCA 树上倍增的更多相关文章

  1. CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)

    CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天, ...

  2. codevs 2370 小机房的树(LCA)

    过了这么长的时间终于开始看LCA了... 有一次训练题卡在LCA当时不会...拖了好久好久...其实现在还是不会... 只会tarjan... 传送门 板子题咯 tarjan的算法就是基于先序遍历的顺 ...

  3. LCA(倍增在线算法) codevs 2370 小机房的树

    codevs 2370 小机房的树 时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...

  4. Codevs 2370 小机房的树

    2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为 ...

  5. codevs——2370 小机房的树

    2370 小机房的树  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 小机房有棵焕狗种的树,树上有N个 ...

  6. 放一道比较基础的LCA 的题目把 :CODEVS 2370 小机房的树

    题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...

  7. 【codevs2370】小机房的树 LCA 倍增

    2370 小机房的树  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...

  8. [CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)

    Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花 ...

  9. [codevs2370]小机房的树<LCA>

    题目链接:http://codevs.cn/problem/2370/ 这题我还是做了比较久了,因为有人告诉我这是用tarjan离线做 好吧算我是蒟蒻,真心不懂tarjan怎么做,最后还是用倍增做的 ...

随机推荐

  1. java18

    1:Map(掌握) (1)将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. (2)Map和Collection的区别? A:Map 存储的是键值对形式的元素,键唯一,值可以重 ...

  2. javascript删除数组某个元素

    1.首先可以给js的数组对象定义一个函数,用于查找指定的元素在数组中的位置,即索引 Array.prototype.indexOf = function(val) { for (var i = 0; ...

  3. NameError: name 'sys_platform' is not defined

    pip install --upgrade distribute

  4. firefox

    ctrl  l            定位到地址栏 f6            同ctrl  l ctrl  k            定位到搜索框 shift  delete        删除地址 ...

  5. 水平时间轴 html + css

    比较粗糙,效果如图 这个是写微信页面时写的,pc 也是一样的效果 代码如下: <div class="time_line_box"> <div class=&qu ...

  6. quartz 线程问题

    2个任务一起使用quartz来调度,但是有一个任务总是会莫名其妙的暂停掉,排查了下,原来组内成员在写JOB任务时候,在JOB中写了个while(true) {    执行业务    休眠10分钟} 导 ...

  7. Python 打包和发布方法汇总

    以下主要Python打包汇总,作为学习备份: 一.使用python内部基础工具包Distutils打包程序 1. 在打包之前需要做的就是配置好安装脚本,一般为setup.py文件: 示例(setup. ...

  8. LeetCode——Best Time to Buy and Sell Stock III (股票买卖时机问题3)

    问题: Say you have an array for which the ith element is the price of a given stock on day i. Design a ...

  9. 初学微信小程序

    最近微信推出了微信小程序,为此我学了几天,基本了解了组件及简单语法,但是今天我自己想要独立写一个demo时,忽然发现难道我的不是微信小程序的语法(我以前是iOS 开发,不用css),而是css样式的设 ...

  10. SPSS回归分析结果解读【来自百度知道】

    R平方就是拟合优度指标,代表了回归平方和(方差分析表中的0.244)占总平方和(方差分析表中的0.256)的比例,也称为决定系数.你的R平方值为0.951,表示X可以解释95.1%的Y值,拟合优度很高 ...