构造访问数组:
void make_bin()
{
bin[0]=1;
for(int i=1;i<=15;i++)
bin[i]=bin[i-1]<<1;
}
构造邻接表:
void Link()
{
for(int i=1;i<=n-1;i++){//n-1 edges;or you can define a m pointing to the number of edges;
scanf("%d%d",&u[i],&v[i]);
//u[i+n-1]=v[i];v[i+n-1]=u[i];//双向;
next[i]=first[u[i]];
//next[i+n-1]=first[v[i]];//双向;
first[u[i]]=i;
//first[v[i]]=i+n-1;//双向;
isroot[v[i]]=true;
}
}
宽搜:
void bfs()
{
int head=0,tail=1;
q[0]=root,vis[root]=true;
while(head^tail){
int now=q[head];head++;
for(int i=1;i<=15;i++){
if(bin[i]<=deep[now])
fa[now][i]=fa[fa[now][i-1]][i-1];
else break;
}
for(int i=first[now];i;i=next[i])
if(!vis[v[i]]){
vis[v[i]]=true;
fa[v[i]][0]=now;
deep[v[i]]=deep[now]+1;
q[tail++]=v[i];
}
}
}
求lca:
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int t=deep[x]-deep[y];
for(int i=0;i<=15;i++)
if(t&bin[i])x=fa[x][i];
for(int i=15;i>=0;i--)
if(fa[x][i]^fa[y][i])
x=fa[x][i],y=fa[y][i];
if(!(x^y))return y;
return fa[x][0];
}
入门题:POJ1330
复杂度为 nlogn
题目代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define mst(x,y) memset(x,y,sizeof(x));
using namespace std;
const int maxn = 1e4+4;
int father[maxn][16];
int u[maxn],v[maxn];
int first[maxn],next[maxn],depth[maxn],q[maxn];
bool isroot[maxn];
int bin[16];
int n;
int root;
bool vis[maxn];
void make_bin(){
bin[0] = 1;
for(int i=1;i<=15;i++){
bin[i] = bin[i-1]<<1;
}
}
void link(){
for(int i=1;i<n;i++){
scanf("%d %d",&u[i],&v[i]);
next[i] = first[u[i]];
first[u[i]] = i;
isroot[v[i]] = true;
}
for(int i=1;i<=n;i++){
if(!isroot[i]){
root = i;
break;
}
}
}
void bfs(){
int head = 0,tail = 1;
q[0] = root;vis[root] = true;
while(head^tail){
int now = q[head];head++;
for(int i=1;i<=15;i++){
if(bin[i] < depth[now]){
father[now][i] = father[father[now][i-1]][i-1];
}else{
break;
}
}
for(int i=first[now];i;i=next[i]){
if(!vis[v[i]]){
vis[v[i]] = true;
father[v[i]][0] = now;
depth[v[i]] = depth[now]+1;
q[tail++] = v[i];
}
}
}
}
int lca(int x,int y){
if(depth[x] < depth[y]){
swap(x,y);
}
int t = depth[x] - depth[y];
for(int i=0;i<=15;i++){
if(t&bin[i]) x = father[x][i];
}
for(int i=15;i>=0;i--){
if(father[x][i]^father[y][i]){
x=father[x][i];y=father[y][i];
}
}
if(!(x^y)) return y;
return father[x][0];
}
void init(){
mst(vis,false);
mst(isroot,false);
mst(u,0);
mst(v,0);
mst(first,0);
mst(next,0);
mst(father,0);
mst(depth,0);
mst(q,0);
}
int main(){
int t;
make_bin();
scanf("%d",&t);
while(t--){
init();
scanf("%d",&n);
link();
bfs();
int x,y;
scanf("%d %d",&x,&y);
printf("%d\n",lca(x,y));
}
return 0;
}