//最近公共祖先 lca
//演算法思想:對一棵樹進行深搜回溯標號,那麼兩個節點的最近公共祖先就是兩個節點第一次標號之間深度最小(非標號,因為回溯會增大那個節點,雖然該節點第一次標號很小)的那個對應的節點
//poj1330
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std ;
const int maxn = 1e4 + 10 ;
int rmq[ 2* maxn ] ;
int dp[maxn * 2 ][20 ] ;
void rmq(int n )
//給出兩個節點第一次的標號,返回最近公共祖先的標號
int query(int i , int j )
struct edgeedge[ maxn * 2 ];
int tot , head [maxn ] ;
int f[maxn * 2 ] ;
int p[maxn] ;
int cnt ;
void ini()
void addedge( int u , int v )
//當前節點u,父節點pre,深度dep
void dfs( int u , int pre , int dep)
}void inilca( int root , int num )
int querylca( int u , int v )
bool flag [maxn] ;
int main()
//有根樹找出根節點
int root ;
for( int i = 1;i<=n ;i++)
}inilca( root , n ) ;
scanf("%d
%d" , & u , & v ) ;
printf("%d\n" , querylca( u , v ) ) ;
} return
0 ;}
//倍增法
//poj1330
//倍增法思想:首先獲得任意節點第2^i個祖父節點的fa陣列
//對於給定的兩個點,對於其中最淺的那個節點,對最深的那個節點取他和最淺的節點相同一層的父節點
//如果該父節點和最淺的節點相同,則代表最淺的節點是最深的節點的最近公共祖先
//否則,通過fa陣列不斷將兩個節點按照各自的路徑上浮,直到他們是乙個節點的兩個子節點,那麼這個父節點就是原來兩個點的最近公共祖先
#include
#include
#include
#include
#include
#include
using
namespace
std ;
const
int maxn = 1e4 + 10 ;
const
int deg = 20 ;
struct edgeedge[maxn* 2];
int head[maxn] , tot ;
void addedge( int u , int v )
void init()
//節點i的第2^i個祖先
int fa[maxn][deg] ;
//深度
int deg[maxn] ;
void dis()
for( int i = head[tmp ] ; i!= -1 ; i= edge[i].next )
}}int lca( int u , int v )
//tu和tv處於同一層並且是乙個父節點的兩個子節點,任取tu或者tv的父節點
return fa[tu][0] ;
}bool flag[maxn] ;
int main()
int root ;
for( int i = 1 ;i<= n ;i++)
if( !flag[i] )
bfs( root ) ;
// dis() ;
scanf("%d%d" , & u , & v ) ;
printf("%d\n" , lca( u , v )) ;
} return
0 ;}
//最近公共祖先lca
//離線演算法 : tarjan
//poj1330
#include
#include
#include
#include
#include
using
namespace
std ;
const
int maxn = 1e4 + 10 ;
const
int maxm = 1e5 + 10 ;
int f[maxn] ;
int find( int x )
void bing( int u , int v )
bool vis[maxn] ;
int ancestor[maxn] ;
struct edgeedge[maxn* 2 ];
int head[maxn] , tot ;
void addedge( int u , int v )
struct queryquery[maxm* 2 ];
int answer[maxm] ;
int h[maxm ] ;
int tt , q ;
void add_query( int u , int v , int index )
void init()
void lca( int u )
for( int i= h[u] ; i!= -1 ; i= query[i].next )
}bool flag[maxn] ;
int main()
scanf("%d%d" , & u , & v ) ;
add_query( u ,v , 0 ) ;
int root ;
for( int i = 1 ;i<= k ;i++)
if( !flag[i] )
lca( root ) ;
cout
<0]0 ;}
最近公共祖先 LCA 最近公共祖先
直接暴力搜尋參考 普通搜尋每次查詢都需要 樸素演算法是一層一層往上找,倍增的話直接預處理出乙個 具體做法是 維護乙個 的關係來線性求出這個陣列 int anc n 31 int dep n 記錄節點深度 void dfs int u,int parent for int i 0 i g u size...
最近公共祖先 最近公共祖先(LCA)
如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。輸入格式 第一行包含三個正整數n m s,分別表示樹的結點個數 詢問的個數和樹根結點的序號。接下來n 1行每行包含兩個正整數x y,表示x結點和y結點之間有一條直接連線的邊 資料保證可以構成樹 接下來m行每行包含兩個正整數a b,表示詢問...
LCA 最近公共祖先
定義 對於有根樹t的兩個結點u v,最近公共祖先lca t,u,v 表示乙個結點x,滿足x是u v的祖先且x的深度盡可能大。另一種理解方式是把t理解為乙個無向無環圖,而lca t,u,v 即u到v的最短路上深度最小的點。現在給定乙個根為1的樹,求某兩個點的最近公共祖先。思路 預處理出每個點的深度再一...