LCA的RMQ求法

Posted linhaitai

tags:

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

参考博客

仔细想一想:最近的公共祖先,其实,搜索时回朔,连通这两点,那深度最低肯定是最近的公共祖先啊。

那这样就可以变成RMQ问题了。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int max_=41005;
int ip,tot;
struct Tree{//
   int to;
   int next;
   int v;
};
struct Tree a[max_*2];
int first[max_];//第一次出现的位置
int edge[max_];//边记录next
int de[max_*2];//深度
int id[max_*2];//遍历编号(包含回朔)
int dis[max_];//到根的距离。
int dp[max_*2][25];//st表,记录的是下标
bool vis[max_];//标记数组
void add_edge(int x,int y,int v)//建树
{
    a[++ip].to=y;
    a[ip].v=v;
    a[ip].next=edge[x];
    edge[x]=ip;
}
void dfs(int x,int deep)//dfs遍历
{
    if(vis[x]==0)
    {
        first[x]=tot;//记录第一次
        vis[x]=1;
    }
    de[tot]=deep,id[tot++]=x;
    for(int i=edge[x];i;i=a[i].next)
    {
        int go_to=a[i].to;
        if(vis[go_to])
            continue;
            int go_v=a[i].v;
            dis[go_to]=dis[x]+go_v;//跟新距离
            dfs(go_to,deep+1);
            id[tot]=x,de[tot++]=deep;
    }
}
int Min(int x,int y)//寻找最小深度
{
    if(de[x]>de[y])
        return y;
    else
        return x;
}
void RMQ_ST(int len)
{
    for(int i=0;i<len;i++)//初始化
        dp[i][0]=i;
    for(int j=1;(1<<j)<=len;j++)
        for(int i=0;i+(1<<j)-1<len;i++)
    {
        dp[i][j]=Min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
}
int RMQ_question(int l,int r)
{
    int k=0;
    while((1<<(k+1))<=r-l+1)k++;
    return Min(dp[l][k],dp[r-(1<<k)+1][k]);
}
void itin()
{
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    memset(edge,0,sizeof(edge));
    tot=0;
    ip=0;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        itin();
        int n,m;
        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);
        }
        dfs(1,0);
        RMQ_ST(tot);
    for(int i=0;i<m;i++)
    {
        int u,v,k;
        cin>>u>>v;
        if(first[u]>first[v])//先出现的为左
        {
            k=RMQ_question(first[v],first[u]);
        }
        else
            k=RMQ_question(first[u],first[v]);
        int temp=dis[u]+dis[v]-(2*dis[id[k]]);
        cout<<temp<<endl;
            }
}
    return 0;
}

 

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

LCA在线算法详解

总结LCA的4种求法

LCA的两种求法

LCA转RMQ 方法(预览)

RMQ及运用RMQ求解LCA

RMQ洛谷P3379 RMQ求LCA