LCA的 Trajan 算法

Posted linhaitai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCA的 Trajan 算法相关的知识,希望对你有一定的参考价值。

参考博客

参考博客

根据博客的模拟,就可以知道做法和思想。

现在就是实现他。

例题 :hdu  2586 

题意:m 个询问,x  到  y  的距离,我们的思想就是求出:x到根的距离+y到根的距离-2*(lca[ x ,y ])到跟的距离。

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int max_edge=100005;//边数
const int max_Q=405;//问题
const int max_=40005;//节点
struct  Tree{//树-邻接表
   int to;
   int v;
   int next;
};
struct  Question{//离线-问题
   int to;
   int id;
   int next;
};
struct Tree a[max_edge];//树数组
struct Question b[max_];//问题数组
int N,M;
int edge[max_];//边记录next
int tot1,tot2;
bool vis[max_];//标记数组
int st[max_Q],ed[max_Q];//问题的x和y
int question[max_];//问题-记录next
int fa[max_];//父节点
int dis[max_];//到根的距离
int LCA[max_Q];//问题的LCA
void  add_edge(int x,int y,int v)//建树
{
    a[++tot1].to=y;
    a[tot1].v=v;
    a[tot1].next=edge[x];
    edge[x]=tot1;
}
void add_question(int x,int y,int id)//离线
{
    b[++tot2].to=y;
    b[tot2].id=id;
    b[tot2].next=question[x];
    question[x]=tot2;
}
int find_fa(int x)//寻找父节点
{
    if(fa[x]==x)
        return x;
    return fa[x]=find_fa(fa[x]);
}
void Tarjan(int x)
{
    fa[x]=x;//作为当前的根节点,将其父亲指向自己
    vis[x]=1;//标记
    for(int i=question[x];i;i=b[i].next)//寻找问题中与自己有关节点
    {
        int go_to=b[i].to;
        if(vis[go_to]==true)//如果有关节点走过,记录LCA
            LCA[b[i].id]=find_fa(go_to);
    }
    for(int i=edge[x];i;i=a[i].next)//沿边遍历
    {
        int go_to=a[i].to;
        if(vis[go_to]==false)
            {
                dis[go_to]=dis[x]+a[i].v;//更新距离
                Tarjan(go_to);//递归遍历
                fa[go_to]=x;//归并父节点
            }
    }
}
int main()
{
    int T;
    cin>>T;//测试组数
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        memset(question,0,sizeof(question));
        memset(edge,0,sizeof(edge));
        memset(dis,0,sizeof(dis));
        memset(LCA,0,sizeof(LCA));
        tot1=0,tot2=0;//初始归零
      cin>>N>>M;
      for(int i=0;i<N-1;i++)
      {
          int x,y,v;
          cin>>x>>y>>v;
          add_edge(x,y,v);//双向建边
          add_edge(y,x,v);
      }
      for(int i=0;i<M;i++)
      {
          int x,y;
          cin>>x>>y;
          add_question(x,y,i);
          add_question(y,x,i);//保证找有关点时不漏
          st[i]=x,ed[i]=y;//记录问题的x,y
      }
      Tarjan(1);
      for(int i=0;i<M;i++)
      {
          int temp=dis[st[i]]+dis[ed[i]]-(2*dis[LCA[i]]);//结果
          cout<<temp<<endl;
      }
    }
}

 

以上是关于LCA的 Trajan 算法的主要内容,如果未能解决你的问题,请参考以下文章

Tarjan-LCA算法小记

LCA 算法倍增

LCA 算法ST表

hdu 3836 Equivalent Sets trajan缩点

LCA

hdu 3861 The King’s Problem trajan缩点+二分图匹配