/*
*算法引入:
*树上两点的最近公共祖先;
*对于有根树的两个结点u,v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u,v的祖先且x的深度尽可能大;
*对于x来说,从u到v的路径一定经过点x;
*
*算法思想:
*Tarjan_LCA离线算法;
*Tarjan算法基于dfs的框架,对于新搜到的一个结点,首先创建由这个结点构成的集合,再对当前结点的每个子树进行搜索;
*每搜索完一棵子树,则可确定子树内的LCA询问都已解决,其他的LCA询问的结果必然在这个子树之外;
*这时把子树所形成的集合与当前结点的集合合并,并将当前结点设为这个集合的祖先;
*之后继续搜索下一棵子树,直到当前结点的所有子树搜完;
*
*这时把当前结点也设为已被检查过的,同时可以处理有关当前结点的LCA询问;
*如果有一个从当前结点到结点v的询问,且v已经被检查过;
*则由于进行的是dfs,当前结点与v的最近公共祖先一定还没有被检查;
*而这个最近公共祖先的包含v的子树一定已经搜索过了,那么这个最近公共祖先一定是v所在集合的祖先;
*
*算法步骤:
*对于每一个结点:
*(1)建立以u为代表元素的集合;
*(2)遍历与u相连的结点v,如果没有被访问过,对于v使用Tarjan_LCA算法,结束后将v的集合并入u的集合;
*(3)对于与u有关的询问(u,v),如果v被访问过,则结果就是v所在集合的代表元素;
*
*算法示例:
*HDU2586(How far away?)
*
*题目大意:
*求树上任两点间的距离;
*
*算法思想:
*先dfs一遍,求出到根节点的dis;
*对于某个询问,求u和v的lca,然后res[i]=d[u]+d[v]-2*d[lca(u,v)];
*
**/
struct node{
int to,w,next,lca;
}; int fa[maxn];
int head[maxn*2];
int qhead[maxm];//询问
bool vis[maxn];
ll d[maxn];
ll res[maxm]; node edge[N*2];
node qedge[M];//询问边 int n,m;
int cnt1,cnt2; int findFa(int x){
return fa[x]==x?x:fa[x]=findFa(fa[x]);
} inline void Addedge(int u,int v,int w){
edge[++cnt1].w=w, edge[cnt1].to=v, edge[cnt1].next=head[u], head[u]=cnt1;
edge[++cnt1].w=w, edge[cnt1].to=u, edge[cnt1].next=head[v], head[v]=cnt1;
} inline void Addqedge(int u,int v){
qedge[++cnt2].to=v, qedge[cnt2].next=qhead[u], qhead[u]=cnt2;
//qedge[++cnt2].to=u, qedge[cnt2].next=qhead[v], qhead[v]=cnt2;
} void dfs(int u,int fa,ll w){
d[u]=w;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(v==fa) continue;
dfs(v,u,w+edge[i].w);
}
} void Tarjan_LCA(int u){ //离线LCA算法
fa[u]=u, vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next){
if(!vis[edge[i].to]){
Tarjan_LCA(edge[i].to);
fa[edge[i].to]=u;
}
}
for(int i=qhead[u];i!=-1;i=qedge[i].next){
if(vis[qedge[i].to]){
qedge[i].lca=findFa(qedge[i].to);
res[i]=d[u]+d[qedge[i].to]-2*d[qedge[i].lca]; //两者距离
}
}
} void solve()
{
rep(i,0,n) fa[i]=i;
mem(head,-1); mem(qhead,-1); mem(vis,false);
cnt1=cnt2=0;
int u,v,w;
rep(i,1,n-1){
scanf("%d%d%d",&u,&v,&w);
Addedge(u,v,w);
}
while(m--){
scanf("%d%d",&u,&v);
Addqedge(u,v);
}
dfs(1,-1,0);
Tarjan_LCA(1);
} int main(){
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
solve();
rep(i,1,m)
printf("%lld\n",res[i]);
}
}

LCA-离线tarjan模板的更多相关文章

  1. [POJ1330]Nearest Common Ancestors(LCA, 离线tarjan)

    题目链接:http://poj.org/problem?id=1330 题意就是求一组最近公共祖先,昨晚学了离线tarjan,今天来实现一下. 个人感觉tarjan算法是利用了dfs序和节点深度的关系 ...

  2. 近期公共祖先(LCA)——离线Tarjan算法+并查集优化

    一. 离线Tarjan算法 LCA问题(lowest common ancestors):在一个有根树T中.两个节点和 e&sig=3136f1d5fcf75709d9ac882bd8cfe0 ...

  3. LCA离线Tarjan,树上倍增入门题

    离线Tarjian,来个JVxie大佬博客最近公共祖先LCA(Tarjan算法)的思考和算法实现,还有zhouzhendong大佬的LCA算法解析-Tarjan&倍增&RMQ(其实你们 ...

  4. [HDOJ2874]Connections between cities(LCA, 离线tarjan)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 这题有不连通的情况,特别注意. 觉得是存query的姿势不对,用前向星存了一遍,还是T…… /* ...

  5. 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 ...

  6. LCA(最近公共祖先)——离线 Tarjan 算法

    tarjan算法的步骤是(当dfs到节点u时):1 在并查集中建立仅有u的集合,设置该集合的祖先为u1 对u的每个孩子v:   1.1 tarjan之   1.2 合并v到父节点u的集合,确保集合的祖 ...

  7. poj 1330 LCA (倍增+离线Tarjan)

    /* 先来个倍增 */ #include<iostream> #include<cstring> #include<cstdio> #define maxn 100 ...

  8. POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 13372   Accept ...

  9. Tarjan的LCA离线算法

    LCA(Least Common Ancestors)是指树结构中两个结点的最低的公共祖先.而LCA算法则是用于求两个结点的LCA.当只需要求一对结点的LCA时,我们很容易可以利用递归算法在O(n)的 ...

  10. luogu3379 【模板】最近公共祖先(LCA) Tarjan

    LCA的Tarjan算法是一个离线算法,复杂度$O(n+q)$. 我们知道Dfs搜索树时会形成一个搜索栈.搜索栈顶节点cur时,对于另外一个节点v,它们的LCA便是v到根节点的路径与搜索栈开始分叉的那 ...

随机推荐

  1. 学习PHP中好玩的Gmagick图像操作扩展的使用

    在 PHP 的图像处理领域,要说最出名的 GD 库为什么好,那就是因为它不需要额外安装的别的什么图像处理工具,而且是随 PHP 源码一起发布的,只需要在安装 PHP 的时候添加上编译参数就可以了. G ...

  2. redis的持久化 与事务管理

    1. redis的持久化 Redis的持久化主要分为两部分:RDB(Redis DataBase), AOF(Append Only File) 2. 什么是redis 的持久化        在指定 ...

  3. Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级

    相关文章 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网 ...

  4. P5748-集合划分计数【EGF,多项式exp】

    正题 题目链接:https://www.luogu.com.cn/problem/P5748 题目大意 求将\(n\)的排列分成若干个无序非空集合的方案. 输出答案对\(998244353\)取模. ...

  5. P5287-[HNOI2019]JOJO【KMP】

    正题 题目链接:https://www.luogu.com.cn/problem/P5287 题目大意 开始一个空串,\(n\)个操作 在末尾加入\(x\)个\(c\)字符(保证和\(c\)和前面的字 ...

  6. P3348-[ZJOI2016]大森林【LCT】

    正题 题目链接:https://www.luogu.com.cn/problem/P3348 题目大意 有\(n\)棵树开始只有一个编号为\(1\)的节点且为标记点.\(m\)次操作要求支持 在\(l ...

  7. 常见JS

    1.获取当前月份第一天 var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; v ...

  8. Spring Security 学习+实践

    Spring Security是Spring为解决应用安全所提供的一个全面的安全性解决方案.基于Spring AOP和Servlet过滤器,启动时在Spring上下文中注入了一组安全应用的Bean,并 ...

  9. MySQL安装指导文档

    MySQL 是最流行的关系型数据库管理系统,可以在本地搭建一个mysql的环境,便于学习. windows7/windows10 5.7.26 安装mysql前环境准备工作 1) 要有Net fram ...

  10. 踩坑系列《七》解决VMware安装完成之后,不能联网的问题

    成功安装CentOS 6.5 好之后,它是默认并不能联网,这时候得需要对root用户进行网络设置 1.先登录root账户 2.命令行输入以下命令,修改配置文件 vim /etc/sysconfig/n ...