最近公共祖先LCA---線上倍增演算法
阿新 • • 發佈:2018-12-20
線上求LCA,多次詢問。倍增演算法時間複雜度為。
1、dfs求每個節點所在層數
void dfs(int u,int root,int d) { int i; depth[u]=d; fa[u][0]=root;//初始化 int sz=edge[u].size(); for(i=0;i<sz;i++) { int v=edge[u][i].v; int w=edge[u][i].w; if(v!=root) { dis[v]=dis[u]+w; dfs(v,u,d+1); } } }//搜尋出各點的深度,以1為根節點,根節點的深度為0
2、倍增演算法預處理出每個節點向上推移2的j次方後的節點
void bz()
{
int i,j;
for(j=1;(1<<j)<=N;j++)
{
for(i=1;i<=n;i++)
{
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
3、查詢最近公共祖先
類似於二分的思想,兩個節點按2的i(1,2,3,4,...)次方向上推移,推移到一定程度,他們的祖先序列完全相同。如果推移一段時間後找到這兩個節點相同的祖先了,那麼這個祖先節點一定是最近公共祖先或者最近公共祖先的祖先,向下搜尋;否則,繼續向上找。
int LCA(int u,int v) { if(depth[u]<depth[v]) swap(u,v);//保證深度較大的為u int dc=depth[u]-depth[v]; int i; for(i=M-1;i>=0;i--) if((1<<i)&dc) u=fa[u][i]; if(u==v) return u;//u移到了和v一個點,該點就是他們的最近公共祖先 for(i=M-1;i>=0;i--)//u和v現在已經在一層,他們往上走幾層之後祖先序列相同 {//找到最小的不滿足相同序列的點, if(fa[u][i]!=fa[v][i]) { u=fa[u][i]; v=fa[v][i]; } } return fa[u][0];//最後,最近公共祖先為找到的點的祖先 }