一道LCA的模板题。
代码:
#include <cstdio>
#include <algorithm>
#include<map>
#include<string.h>
#include<iostream>
#define MAXN 1000010
#define MAXM 1000010
using namespace std;
map<string,int>MAP;
map<int,string>MAP2;
struct Edge
{
int from, to, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int vs[MAXN<<1];//第i次DFS访问节点的编号
int depth[MAXN<<1];//第i次DFS访问节点的深度
int id[MAXN];//id[i] 记录在vs数组里面 i节点第一次出现的下标
int dfs_clock;//时间戳
int N, M, Q;//点数 边数 查询数
int dp[MAXN<<1][20];//dp[i][j]存储depth数组 以下标i开始的,长度为2^j的区间里 最小值所对应的下标
void init()
{
edgenum = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v)
{
Edge E = {u, v, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
void getMap()
{
int cnt=0;
int a, b;
string h1,h2;
while(M--)
{
cin>>h1>>h2;
if(!MAP[h1])
{
MAP[h1]=++cnt;
MAP2[cnt]=h1;
}
if(!MAP[h2])
{
MAP[h2]=++cnt;
MAP2[cnt]=h2;
}
addEdge(MAP[h1], MAP[h2]), addEdge(MAP[h2], MAP[h1]);
}
}
void DFS(int u, int fa, int d)//当前遍历点以及它的父节点 遍历点深度
{
id[u] = dfs_clock;
vs[dfs_clock] = u;
depth[dfs_clock++] = d;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == fa) continue;
DFS(v, u, d+1);
vs[dfs_clock] = u;//类似 回溯
depth[dfs_clock++] = d;
}
}
void find_depth()
{
dfs_clock = 1;
memset(vs, 0, sizeof(vs));
memset(id, 0, sizeof(id));
memset(depth, 0, sizeof(depth));
DFS(1, -1, 0);//遍历
}
void RMQ_init(int NN)//预处理 区间最小值
{
for(int i = 1; i <= NN; i++)
dp[i][0] = i;
for(int j = 1; (1<<j) <= NN; j++)
{
for(int i = 1; i + (1<<j) - 1 <= NN; i++)
{
int a = dp[i][j-1];
int b = dp[i + (1<<(j-1))][j-1];
if(depth[a] <= depth[b])
dp[i][j] = a;
else
dp[i][j] = b;
}
}
}
int query(int L, int R)
{
//查询L <= i <= R 里面使得depth[i]最小的值 返回对应下标
int k = 0;
while((1<<(k+1)) <= R-L+1) k++;
int a = dp[L][k];
int b = dp[R - (1<<k) + 1][k];
if(depth[a] <= depth[b])
return a;
else
return b;
}
int LCA(int u, int v)
{
int x = id[u];//比较大小 小的当作左区间 大的当作右区间
int y = id[v];
if(x > y)
return vs[query(y, x)];
else
return vs[query(x, y)];
}
void solve()
{
string a, b;
while(Q--)
{
cin>>a>>b;
int p=LCA(MAP[a], MAP[b]);
cout<<MAP2[p]<<endl;
}
}
int main()
{
scanf("%d",&M);
init();
getMap();
find_depth();//DFS遍历整个树 求出所需要的信息
RMQ_init(dfs_clock - 1);
scanf("%d",&Q);
solve();
return 0;
}