RMQ求LCA模板:

//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 150
#define N 10007
using namespace std;


struct node
{
    int v,w;
    int next;
}g[N];
int head[N],ct;

int vNum[2*N],fNum[N],depth[2*N];
int cnt;
int dp[2*N][20];
int pow2[20],ind[N];
bool vt[N];
int n;

void init()
{
    cnt = 0;
    CL(head,-1);
    CL(ind,0);
    ct = 0;
}
void add(int u,int v)
{
    g[ct].v = v;
    g[ct].next = head[u];
    head[u] = ct++;
}
void dfs(int u,int dep)
{
    vt[u] = true;
    vNum[cnt] = u;//记录dfs的每个节点
    depth[cnt] = dep;//记录dfs每个节点的深度
    fNum[u] = cnt;//记录每节点第一次出现的编号
    cnt++;
    for (int i = head[u]; i != -1; i = g[i].next)
    {
        int v = g[i].v;
        if (!vt[v])
        {
            dfs(v,dep + 1);
            vNum[cnt] = u;
            depth[cnt] = dep;
            cnt++;
        }
    }
}
int imin(int i,int j)
{
    if (depth[i] < depth[j]) return i;
    else return j;
}
void init_rmq()
{
    int i,j;
    for (i = 0; i < cnt; ++i) dp[i][0] = i;
    for (j = 1; pow2[j] <= cnt; ++j)
    {
        for (i = 0; i + pow2[j] - 1 < cnt; ++i)
        {
            dp[i][j] = imin(dp[i][j - 1],dp[i + pow2[j - 1]][j - 1]);
        }
    }
}
int rmq(int l,int r)
{
    int k = (int)(log(1.0*(r - l + 1))/log(2.0));
    return imin(dp[l][k],dp[r - pow2[k] + 1][k]);
}
int main()
{
    int i,T;
    int x,y;
    for (i = 0; i <= 20; ++i) pow2[i] = 1<<i;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        init();
        for (i = 0; i < n - 1; ++i)//n-1条边
        {
            scanf("%d%d",&x,&y);
            ind[y]++;//统计每个节点入度找出根节点
            add(x,y);
        }
        //找根节点
        int root = 0;
        for (i = 1; i <= n; ++i)
        {
            if (ind[i] == 0)
            {
                root = i;
                break;
            }
        }
        //dfs给每一个节点编号,并且记录深度
        CL(vt,false);
        dfs(root,0);
        //rmq处理
        init_rmq();
        scanf("%d%d",&x,&y);
        if (fNum[x] <= fNum[y]) printf("%d\n",vNum[rmq(fNum[x],fNum[y])]);
        else printf("%d\n",vNum[rmq(fNum[y],fNum[x])]);
    }
    return 0;
}

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值