代码
//maxn是点的最大个数,首先init,然后用G加边,接下来调用dfs(根,1),ST(节点个数), //GetLca(u,v)用于查询两点的lca typedef pair<int,int> par; struct LCA { int id,ver[maxn*2],deep[maxn*2];//id先序访问编号,ver保存id对应节点编号,deep深度 int disc[maxn],fa[maxn]; //disc点被访问时的id,fa父节点 bool vis[maxn]; //是否被访问过 vector<int> G[maxn]; //邻接表 void init(int n=maxn-1) //初始化 { id=0; for(int i=0;i<=n;i++) { vis[i]=false; G[i].clear(); fa[i]=-1; } } void dfs(int u,int h) //深搜一遍把对应信息保存下来 { vis[u]=true; ver[++id]=u; deep[id]=h; disc[u]=id; int Size=G[u].size(); for(int i=0;i<Size;i++) { int v=G[u][i]; if(vis[v]) continue; fa[v]=u; dfs(v,h+1); ver[++id]=u; deep[id]=h; } return; } int Lg[2*maxn]; par dp[2*maxn][18]; int f(int x){ return 1<<x; } void ST(int n) //RMQ处理部分 { n*=2; Lg[0]=-1; for(int i=1;i<=n;i++) Lg[i]=Lg[i-1]+((i&(i-1))?0:1); for(int i=1;i<=n;i++) dp[i][0]=make_pair(deep[i],ver[i]); //深度和点编号 for(int j=1;f(j)<=n;j++) for(int i=1;i+f(j)-1<=n;i++) dp[i][j]=min(dp[i][j-1],dp[i+f(j-1)][j-1]);//lca一定是深度最小的位置 } int GetLca(int u,int v) { int x=disc[u],y=disc[v]; if(x>y) swap(x,y); int k=Lg[y-x+1]; par t=min(dp[x][k],dp[y-f(k)+1][k]); return t.second; } }lca;