poj1986 LCA转化为RMQ在线算法模板题

Posted 文竹balala

tags:

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

 分析:这道题就是求一个最近公共祖先,然后结果就是两点到根的距离减去LCA(u, v)到根的距离。



#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <cmath>
#define ll long long
using namespace std;
const int maxn = 100000 + 5;
struct Eage
    int to, next, w;
eage[maxn*2];
int cnt, tim = 0, n, depth = 0;
int head[maxn];
int pos[maxn];//节点在深度序列中首次出现的深度
int f[maxn];//深搜序列
int b[maxn*2];//深度序列,注意每个节点的深度是不同的
ll dis[maxn];//节点到根的距离
int dp[maxn][15];
void add(int x, int y, int z)

    eage[cnt].to = y;
    eage[cnt].w = z;
    eage[cnt].next = head[x];
    head[x] = cnt++;


void dfs1(int u, int fa)

    //cout << u << " ";
    int deep = ++depth;
    f[deep] = u;
    b[++tim] = deep;
    pos[u] = tim;
    for (int i = head[u]; i != -1; i = eage[i].next)
    
        int v = eage[i].to;
        if (v == fa) continue;
        dis[v] = dis[u] + eage[i].w;
        dfs1(v, u);
        b[++tim] = deep;
    

void rmq_st(int n)

    for (int i = 1; i <= n; i++) dp[i][0] = b[i];
    int m = (int) (log(1.0*n)/log(2.0));//注意括号
    for (int j = 1; j <= m; j++)
    
        int t = n - (1<<j)+1;
        for (int i = 1; i <= t; i++)
        
            if (dp[i][j-1] < dp[i+(1<<(j-1))][j-1]) 
                dp[i][j] = dp[i][j-1];
            
            else 
                dp[i][j] = dp[i+(1<<(j-1))][j-1];
            
        
    

int rmq_find(int l, int r)

    int k = (int)(log(1.0*(r-l+1)) / log(2.0));
    return min(dp[l][k], dp[r-(1<<k)+1][k]);


int main()

    //freopen("input.txt", "r", stdin);
    int  m;
    cin >> n >> m;
    cnt = 0;
    tim = 0;
    memset(head, -1, sizeof(head));
    memset(pos, -1, sizeof(pos));
    memset(dis, 0, sizeof(dis));
    for (int i = 1; i <= m; i++)
    
        int x, y, z;
        char ch;
        scanf("%d%d%d %c", &x, &y, &z, &ch);
        add(x, y, z);
        add(y, x, z);
    
    dfs1(1, 0);
    rmq_st(2*n-1);
    int k;
    cin >> k;
    for (int i = 0; i < k; i++)
    
        int a, b;
        scanf("%d%d", &a, &b);
        if (pos[a] > pos[b]) swap(a, b);
        int  k = rmq_find(pos[a], pos[b]);
        cout << dis[a]+dis[b]-2*dis[f[k]] << endl;
    
    return 0;



以上是关于poj1986 LCA转化为RMQ在线算法模板题的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1986:Distance Queries(倍增求LCA)

LCA上的RMQ模板算法

POJ 1986 Distance Queries(LCA)

poj2763(lca / RMQ + 线段树)

LCA算法_普通做法&倍增&Tarjan&RMQ

hdu2874(lca / tarjan离线 + RMQ在线)