详细讲解见:
https://blog.csdn.net/liangzhaoyang1/article/details/52549822
zz:https://www.cnblogs.com/kuangbin/p/3302493.html

/* ***********************************************
Author :kuangbin
Created Time :2013-9-5 0:09:55
File Name :F:\2013ACM练习\专题学习\LCA\POJ1330.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
/*
* LCA (POJ 1330)
* 在线算法 DFS + ST
*/
const int MAXN = 10010;
int rmq[2*MAXN];//rmq数组,就是欧拉序列对应的深度序列
struct ST
{
int mm[2*MAXN];
int dp[2*MAXN][20];//最小值对应的下标
void init(int n)
{
mm[0] = -1;
for(int i = 1;i <= n;i++)
{
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dp[i][0] = i;
}
for(int j = 1; j <= mm[n];j++)
for(int i = 1; i + (1<<j) - 1 <= n; i++)
dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
}
int query(int a,int b)//查询[a,b]之间最小值的下标
{
if(a > b)swap(a,b);
int k = mm[b-a+1];
return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
}
};
//边的结构体定义
struct Edge
{
int to,next;
};
Edge edge[MAXN*2];
int tot,head[MAXN]; int F[MAXN*2];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
int P[MAXN];//P[i]表示点i在F中第一次出现的位置
int cnt; ST st;
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)//加边,无向边需要加两次
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u,int pre,int dep)
{
F[++cnt] = u;
rmq[cnt] = dep;
P[u] = cnt;
for(int i = head[u];i != -1;i = edge[i].next)
{
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u,dep+1);
F[++cnt] = u;
rmq[cnt] = dep;
}
}
void LCA_init(int root,int node_num)//查询LCA前的初始化
{
cnt = 0;
dfs(root,root,0);
st.init(2*node_num-1);
}
int query_lca(int u,int v)//查询u,v的lca编号
{
return F[st.query(P[u],P[v])];
}
bool flag[MAXN];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int N;
int u,v;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
init();
memset(flag,false,sizeof(flag));
for(int i = 1; i < N;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
flag[v] = true;
}
int root;
for(int i = 1; i <= N;i++)
if(!flag[i])
{
root = i;
break;
}
LCA_init(root,N);
scanf("%d%d",&u,&v);
printf("%d\n",query_lca(u,v));
}
return 0;
}

  

最新文章

  1. 用 const 还是用 let?
  2. css浮动(folat),清除浮动(clear)(另加两种清除浮动方式,总共三种清除浮动方式)
  3. fatal: Not a git repository (or any of the parent directories): .git
  4. java实现身份证校验
  5. STL学习系列八:Set和multiset容器
  6. 抽象工厂(Abstract Factory)模式
  7. 教程-Delphi7 自带控件安装对应表
  8. Glibc和GCC,ARM-LINUX-GCC的关系
  9. GWT 实现文件上传和下载
  10. git开源项目协作
  11. Android 开机启动通知
  12. nc命令 (NetCat)
  13. Struts2 注解(转)
  14. firefox的window.onerror没有详细的出错提示
  15. 理解Twisted与非阻塞编程
  16. mysql zip 版安装
  17. CWnd *和HWnd转换
  18. ActiveMQ的消息持久化机制
  19. 解决idea中 mvn项目导了包找不到包的问题
  20. div左右居中css

热门文章

  1. hdu 6205 card card card 最大子段和
  2. nginx的反向代理和配置
  3. PrimeFaces ab function
  4. java常用关键词关键字,方法源码解析
  5. HYSBZ-4033-树上染色(树上DP)
  6. 2019春Python程序设计作业2(0326--0401)
  7. jsonp跨域实例
  8. 镜像源操作-ananconda-docker
  9. 洛谷 P1140 相似基因 ( 线性DP || 类LCS )
  10. gdal test