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)