这道题与之前那两道模板题不同的是,路径有了权值,而且边是双向的,root已经给出来了,就是1,(这个地方如果还按之前那样来计算入度是会出错的.数据里会出现多个root...数据地址可以在poj的discuss板块看到).两个节点之间的距离,可以这样处理:先处理出每个节点i到根的距离dist[i],则节点a,b之间的距离就是dist[a]+dist[b]-2*dist[LCA(a,b)],或者是在LCA的过程中加一个形式变量来传递距离值(目测这样效率会更高).我一开始是想的仅传递每层的距离,具体怎…
本文来自:http://www.cnblogs.com/Findxiaoxun/p/3428516.html 写得很好,一看就懂了. 在这里就复制了一份. LCA问题: 给出一棵有根树T,对于任意两个结点u,v求出LCA(T, u, v),即离根最远的结点x,使得x同时是u和v的祖先. 把LCA问题看成询问式的:给出一系列询问,程序应当对每一个询问尽快做出反应. 对于这类问题有两种解决方法;一是用比较长的时间做预处理,但是等信息充足以后每次回答询问只需要用比较少的时间.这样的算法叫做在线算法.…
一. 离线Tarjan算法 LCA问题(lowest common ancestors):在一个有根树T中.两个节点和 e&sig=3136f1d5fcf75709d9ac882bd8cfe0cd" alt="">的近期公共祖先.指的是二者的公共祖先中深度最高的节点. 给定随意两个树中的节点,求它们的近期公共祖先. 对于二分查找树.二叉树,能够用普通的dfs实现.但对于多叉树.查询次数频繁的情况下.离线Tarjan算法的长处就显现出来了.因为对树上全部节点仅仅进…
      树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4)一个点地一个点地往上跳,直到到某个点(3)和另外那个点(5)的深度一样 然后两个点一起一个点地一个点地往上跳,直到到某个点(就是最近公共祖先)两个点"变"成了一个点 不过有没有发现一个点地一个点地跳很浪费时间? 如果一下子跳到目标点内存又可能不支持,相对来说…
离线算法也就是需要先把所有查询给保存下来,最后一次输出结果. 离线算法是基于并查集实现的,首先就是初始化P[i] = i. 接下来对于每个点进行dfs: ①首先判断是否有与该点有关的查询,如果当前该点为u,与它有关的点为v,如果v已经访问过了,那么它们的LCA就是find(v).如果v还没有访问,那就不用管它. ②对该点的子节点继续dfs,需要注意的是,dfs完之后需要需要p[v]=u,将v点并到其父亲节点上. void LCA(int u) { vis[u]=; ;i=query[i].nex…
hdu 2586:题意:输入n个点的n-1条边的树,m组询问任意点 a b之间的最短距离 思路:LCA中的Tarjan算法,RMQ还不会.. #include <stdio.h> #include <iostream> #include <string.h> using namespace std; ; ; int head[N]; //树边邻接表的表头 int __head[N]; //保存询问的邻接表的表头 struct edge{ //保存边 int u,v,w,…
距离B - Distance in the Tree 还是普通的LCA但是要求的是两个节点之间的距离,学到了一些 一开始我想用带权并查集进行优化,但是LCA合并的过程晚于离线计算的过程,所以路径长度会有所偏差 所以失败告终 网上查询之后懂得要提前进行一下预处理,在输入完全部的边之后,也就是数形成之后,计算dis——>也就是每个点到树根的长度 之后进行询问查询时:u,v 和 rt 这样uv的距离就是dis[u] + dis[v] - 2 * dis[rt]很好理解 时间复杂度也还可以 #inclu…
给出N个点,M条边.Q次询问 Q次询问每两点之间的最短距离 典型LCA 问题   Marjan算法解 #include "stdio.h" #include "string.h" struct Edge { int to,next,len; }edge[20010]; struct Ques { int to,next,index; }ques[2000010]; int head[10010],q_head[10010],f[10010],dis[10010];…
tarjan算法的步骤是(当dfs到节点u时):1 在并查集中建立仅有u的集合,设置该集合的祖先为u1 对u的每个孩子v:   1.1 tarjan之   1.2 合并v到父节点u的集合,确保集合的祖先是u2 设置u为已遍历3 处理关于u的查询,若查询(u,v)中的v已遍历过,则LCA(u,v)=v所在的集合的祖先 不懂请点击 伪代码: Tarjan(u)//marge和find为并查集合并函数和查找函数 { for each(u,v) //访问所有u子节点v { Tarjan(v); //继续…
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * (r,fa(lca))\). (树上差分) 求法 tarjan 离线算法, 总时间 \(O(n+q)\). (q表示询问次数) //利用前向星存储询问 struct te{int t,pr,lca;}edge[1000050],qedge[1000050]; int head[500050],pe…