lca還是圖論中蠻重要的部分,解法眾多,這裡只拿三個比較常用的板子出來說說
1.樹上倍增
1.1演算法原理
1.2演算法實現
2.tarjan演算法
2.1演算法原理
2.2演算法實現
3.rmq實現
3.1演算法原理
3.2演算法實現
4.總解
倍增演算法主要是利用\(2^i\)可以相加組成任何數這一性質來組織資訊轉移狀態,具體就是維護乙個倍增陣列\(f[i][j]\)表示編號為\(i\)的節點向上跳\(2^j\)步所到達的點。通過簡單的思考我們可以發現節點\(i\)向上跳\(2^j\)步的節點是\(i\)號節點向上跳\(2^\)步的節點再向上跳\(2^\)步所到達的節點,因此我們可以得到乙個式子:\(f[i][j]=f[f[i][j-1]][j-1]\),通過這個式子,我們可以輕易的在很短的時間內推出倍增陣列。
而有了倍增陣列就好辦了,我們可以利用dfs求出每個節點距根節點的深度,然後我們便可以先將兩個節點上跳到同一高度(注:以後上跳都可以利用倍增陣列完成),再將兩個節點同時上跳。當兩個節點的祖先都相同時,便找到了兩個節點的最近公共祖先。
該演算法單個查詢的時間複雜度為\(o(log(n))\)。
**如下#include #include #include #include #include #include #include using namespace std;
vectortree[1005];
int deep[1005];
int anc[1005][25];
int father[1005];
void dfs(int root)//預處理出倍增陣列和深度
int len=tree[root].size();
for(int i=0;i=0;i--)//將兩個點調整到同一高度
}if(a==b)
for(int i=19;i>=0;i--)
}return anc[a][0];
}int main()
father[1]=1;
dfs(1);
for(int i=1;i<=t;i++)
memset(used,0,sizeof(used));
return ;
}int find(int x)
return father[x]=find(father[x]);
} void unions(int x, int y)
father[x]=y;
return ;
}void tarjan(int root)
]\)的區間的最值。而通過動態規劃我們便可以預處理出\(f\)陣列。首先\(f[i][0]\)的值就是它本身,而\(f[i][j]\)可以分為\((i,i+2^-1)\)和\((i+2^,i+2^j-1)\)兩段區間使得兩段區間長度都為\(2^\)。這樣便可以得到狀態轉移方程\(f[i][j]=max(f[i][j-1],f[i+2^][j-1])\)。
而rmq的查詢可以通過乙個中間值\(k=log_(j-i+1)\),則區間\((i,j)\)的最值就為\(max(f[i][k],f[j-2^k+1][k])\)。這樣便可以在\(o(1)\)的時間內查詢區間的最值了。
**如下#include #include #include #include #include #include #include using namespace std;
vectortree[1005];
int cnt=1;
int st[1005<<1][20];
int deep[1005<<1];
int id[1005];
int idx[1005<<1];
void getst(int n)//預處理出st表
for(int j=1;(1return idx[ask(l,r)];
}int main()
dfs(1,-1,0);
getst(2*n);
for(int i=1;i<=t;i++)
{scanf("%d %d",&a,&b);
cout《而tarjan演算法是三種演算法中效率最高的,但因其是離線演算法所以應用範圍不是很廣,在面對大量的詢問是還是乙個不錯的演算法,且其實現簡單,不容易出錯。
在考場上的推薦度為rmq\(\leq\)tarjan\(\leq\)倍增。
LCA問題的三種求法
先來看一道例題 hdu 2586 how far away 題目描述的就是給你一棵n個節點的樹,然後q次詢問,每次詢問的內容是節點x和節點y的最近公共祖先 lca 接下來就來說一說lca 最近公共祖先 你需要準備的預備知識 st表處理rmq問題 並查集的思想以及實現 dfs遍歷整棵樹,維護一些值 求...
C 類模板的三種特化
說起c 的模板及模板特化,相信很多人都很熟悉 但是說到模板特化的幾種型別,相信了解的人就不是很多。我這裡歸納了針對乙個模板引數的類模板特化的幾種型別,一是特化為絕對型別 二是特化為引用,指標型別 三是特化為另外乙個類模板。這裡用乙個簡單的例子來說明這三種情況 general version temp...
C 類模板的三種特化
說起c 的模板及模板特化,相信很多人都很熟悉 但是說到模板特化的幾種型別,相信了解的人就不是很多。我這裡歸納了針對乙個模板引數的類模板特化的幾種型別,一是特化為絕對型別 二是特化為引用,指標型別 三是特化為另外乙個類模板。這裡用乙個簡單的例子來說明這三種情況 general version temp...