前幾天做faebdc學長出的模擬題,第三題最後要倍增來優化,在學長的講解下,嘗試的學習和編了一下倍增求lca(我能說我其他方法也大會嗎?。。)
倍增求lca:
father【i】【j】表示節點i往上跳2^j次後的節點
可以轉移為
father【i】【j】=father【father【i】【j-1】】【j-1】
(此處注意迴圈時先迴圈j,再迴圈i)
然後dfs求出各個點的深度depth
整體思路:
先比較兩個點的深度,如果深度不同,先讓深的點往上跳,淺的先不動,等兩個點深度一樣時,if 相同 直接返回,if 不同 進行下一步;如果不同,兩個點一起跳,j從大到小列舉(其實並不大),如果兩個點都跳這麼多後,得到的點相等,兩個點都不動(因為有可能正好是lca也有可能在lca上方),知道得到的點不同,就可以跳上來,然後不斷跳,兩個點都在lca下面那層,所以再跳1步即可,當father【i】【j】中j=0時即可,就是lca,返回值結束
感謝sunshinezff學長的編碼糾錯幫助
下面是**:「`
#include
#include
#include
#include
#include
using
namespace
std;
vector
g[100010];
int father[100010][40]=;
int depth[100010]=;
int n,m;
bool visit[10010]=;
int root;
void dfs(int u)
}
}//深搜出各點的深度,存在depth中
void bz()
//倍增,處理father陣列,詳情參照上述講解
int lca(int u,int v)
//保證深度大的點為u,方便操作
int dc=depth[u]-depth[v];
int i;
for (i=0;i<30;i++)//值得注意的是,這裡需要從零列舉
//上述操作先處理較深的結點,使兩點深度一致
if (u==v) return u;//如果深度一樣時,兩個點相同,直接返回
for (i=29;i>=0;i--)
}u=father[u][0];//上述過程做完,兩點都在lca下一層,所以走一步即可
return u;
}int main()
depth[root]=1;
dfs(root);
bz();
int x,y;
scanf("%d%d",&x,&y);
printf("%d",lca(x,y));
return
0;
}
倍增法求lca(最近公共祖先)
基本上每篇部落格都會有參考文章,一是彌補不足,二是這本身也是我學習過程中找到的覺得好的資料 大致上演算法的思路是這樣發展來的。想到求兩個結點的最小公共祖先,我們可以先把兩個的深度提到同一水平,在一步一步往上跳,直到兩個結點有了乙個公共祖先,依照演算法流程,這就是least common ancest...
LCA 最近公共祖先 (倍增演算法)
首先了解一下我們 最近公共祖先 e和g的lca為a l和j的lca為d k和f的lca為b 然後 倍增 用到了二進位制和 dp 的思想 倍增 就是 1 2 4 8 16 任何乙個數 都是可以右 這些數相加得到的。了解一下二進位制 首先 定義 fa i j 為 從 i 節點 向上走 2 j 個節點,d...
最近公共祖先 LCA 倍增演算法
樹上倍增求lca lca指的是最近公共祖先 least common ancestors 如下圖所示 4和5的lca就是2 那怎麼求呢?最粗暴的方法就是先dfs一次,處理出每個點的深度 然後把深度更深的那乙個點 4 乙個點地乙個點地往上跳,直到到某個點 3 和另外那個點 5 的深度一樣 然後兩個點一...