题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2586

题目大意:在一个无向树上,求一条链权和。

解题思路

0

|

1

/   \

2      3

设dist[i]为i到根0的链和,求法(Dfs过程中dist[v]=dist[u]+e[i].w)

对于树中任意两点形成的链,可以通过LCA最近公共祖先剖分。

比如2->3,就可以经过LCA点1:  2->1->3

链和=dist[u]+dist[v]-2*dist[LCA[u,v]]

(0-1-2)+(0-1-3)-2*(0-1)=(2-1-3),有点容斥原理的味道。

LCA比较快的是Tarjan离线法,把全部query也做成一个无向树,离线处理。

过程分为两个stage,stage 1对连接树处理,stage 2对query树处理。

两个stage可以颠倒。正写法 倒写法。在Tarjan(u)中,并查集find(v),可以获得LCA。

LCA存储比较头疼,由于LCA是双向共享的。可以建个ancestor数组,索引是查询序号。

也可以直接存在query树的链式前向星中。

本题双向建一个无向树,任意选择一个起点作为root做LCA都可以。

  1. #include "cstdio"
  2. #include "cstring"
  3. #define maxn 40005
  4. #define maxm 205
  5. int head[maxn],qhead[maxn],dist[maxn],tot1,tot2,f[maxn],vis[maxn],ancestor[maxn];
  6. struct Edge
  7. {
  8. int to,next,w;
  9. }e[maxn*];
  10. struct Query
  11. {
  12. int from,to,next,idx;
  13. }q[maxn*];
  14. void addedge(int u,int v,int w)
  15. {
  16. e[tot1].to=v;
  17. e[tot1].w=w;
  18. e[tot1].next=head[u];
  19. head[u]=tot1++;
  20. }
  21. void addquery(int u,int v,int idx)
  22. {
  23. q[tot2].from=u;
  24. q[tot2].to=v;
  25. q[tot2].next=qhead[u];
  26. q[tot2].idx=idx;
  27. qhead[u]=tot2++;
  28. }
  29. int find(int x) {return x!=f[x]?f[x]=find(f[x]):x;}
  30. void Union(int u,int v)
  31. {
  32. u=find(u),v=find(v);
  33. if(u!=v) f[v]=u;
  34. }
  35. void LCA(int u)
  36. {
  37. vis[u]=true;
  38. f[u]=u;
  39. for(int i=head[u];i!=-;i=e[i].next)
  40. {
  41. int v=e[i].to,w=e[i].w;
  42. if(!vis[v])
  43. {
  44. dist[v]=dist[u]+w;
  45. LCA(v);
  46. Union(u,v);
  47. }
  48. }
  49. for(int i=qhead[u];i!=-;i=q[i].next)
  50. {
  51. int v=q[i].to;
  52. if(vis[v]) ancestor[q[i].idx]=find(v);
  53. //or storage e[i].lca=e[i^1].lca=find(v)
  54. }
  55. }
  56. int main()
  57. {
  58. //freopen("in.txt","r",stdin);
  59. int T,n,m,u,v,c;
  60. scanf("%d",&T);
  61. while(T--)
  62. {
  63. tot1=tot2=;
  64. memset(head,-,sizeof(head));
  65. memset(qhead,-,sizeof(qhead));
  66. memset(vis,,sizeof(vis));
  67. dist[]=;
  68. scanf("%d%d",&n,&m);
  69. for(int i=;i<n-;i++)
  70. {
  71. scanf("%d%d%d",&u,&v,&c);
  72. addedge(u,v,c);
  73. addedge(v,u,c);
  74. }
  75. for(int i=;i<m;i++)
  76. {
  77. scanf("%d%d",&u,&v);
  78. addquery(u,v,i);
  79. addquery(v,u,i);
  80. }
  81. LCA();
  82. for(int i=;i<tot2;i=i+)
  83. {
  84. int u=q[i].from,v=q[i].to,idx=q[i].idx;
  85. printf("%d\n",dist[u]+dist[v]-*dist[ancestor[idx]]);
  86. }
  87. }
  88. }

HDU 2586 (LCA模板题)的更多相关文章

  1. [hdu 2586]lca模板题(在线+离线两种版本)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 在线版本: 在线方法的思路很简单,就是倍增.一遍dfs得到每个节点的父亲,以及每个点的深度.然后 ...

  2. hdu - 2586 (LCA板子题)

    传送门 (这次的英文题面要比上一个容易看多了) (英语蒟蒻的卑微) 又是一个很裸的LCA题 (显然,这次不太容易打暴力咧) (但听说还是有大佬用dfs直接a掉了) 正好 趁这个机会复习一下LCA 这里 ...

  3. hdu 2586 How far away?(LCA模板题+离线tarjan算法)

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  4. HDU - 2586 How far away ?(LCA模板题)

    HDU - 2586 How far away ? Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  5. HDU 2586——How far away ?——————【LCA模板题】

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  6. HDU 2138 Miller-Rabin 模板题

    求素数个数. /** @Date : 2017-09-18 23:05:15 * @FileName: HDU 2138 miller-rabin 模板.cpp * @Platform: Window ...

  7. HDU 2586 How far away ?【LCA模板题】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给你N个点,M次询问.1~N-1行输入点与点之间的权值,之后M行输入两个点(a,b)之间的最 ...

  8. HDU 2586 How far away ? 离线lca模板题

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  9. HDU 2586 ( LCA/tarjan算法模板)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离 思路:求出两个村庄的LCA,d ...

随机推荐

  1. Delphi中的接口和抽象类

    参考:http://blog.csdn.net/xinzheng_wang/article/details/6058643 接口:Interface Delphi中接口中的关键字Interface,但 ...

  2. Linux Shell 高级编程技巧2----shell工具

    2.shell工具    2.1.日志文件        简介            创建日志文件是很重要的,记录了重要的信息.一旦出现错误,这些信息对于我们排错是非常有用的:监控的信息也可以记录到日 ...

  3. Linux环境下段错误的产生原因及调试方法小结

    转载自http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基础之 ...

  4. 小鼠迷宫问题【sdut1157】【dfs,bfs综合题目】

    小鼠迷宫问题 Time Limit: 1500ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 小鼠a与小鼠b身处一个m×n的迷宫中,如图所示.每一个方格表示迷宫中 ...

  5. Counterfeit Dollar -----判断12枚钱币中的一个假币

     Counterfeit Dollar Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u ...

  6. Microsoft SQL Server 博客目录

    基础概念篇 SQL Server排序规则 SQL SERVER 统计信息概述(Statistics) SQL SERVER 索引之聚集索引和非聚集索引的描述 Sql Server 索引之唯一索引和筛选 ...

  7. 【leetcode】Reverse Integer

    题目描述: Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 很简单 ...

  8. 配置ogg异构oracle-mysql(2)源端配置

    源端配置大致分为如下三个步骤:配置mgr,配置抽取进程,配置投递进程 在源端先创建一张表,记得带主键: SQL> create table ah4(id int ,name varchar(10 ...

  9. Dwz下拉菜单的二级联动

    在DWZ文档中对组合框combox的是这样描述的: 在传统的select 用class 定义:class=”combox”, html 扩展:保留原有属性name,  增加了属性:ref. ref 属 ...

  10. 利用Visual GDB在Visual Studio中进行Android开发

    转载请注明http://www.cnblogs.com/adong7639/p/4119467.html 无意中发现了Visual GDB这个工具,可以再Visual Studio中进行Android ...