LCA的各類解法(二)——樹鏈剖分求LCA
阿新 • • 發佈:2018-12-30
樹鏈剖分求LCA其實就是樹剖的一個應用.
不會樹剖的點這裡.
樹剖求LCA的速度還很快,O(n)預處理,O(log(n))查詢,相較於倍增LCA更快,而且求LCA那部分更好寫,但是dfs部分比較難寫.
樹剖求LCA相較於倍增最大的優勢是空間複雜度較低,只要O(n).
整個演算法流程就是先兩個dfs預處理,然後一個判斷u與v是否在同一條重鏈,不在就往上跳,最後得到LCA.
至於為什麼查詢是O(log(n))的,因為我們可以證明重鏈只有log(n)條,所以是O(log(n))的.
程式碼如下:
void dfs1(int k,int fa){ nod[k].dad=fa; nod[k].size=1; nod[k].deep=nod[fa].deep+1; for (int i=lin[k];i;i=e[i].next) if (e[i].y^fa){ dfs1(e[i].y,k); nod[k].size+=nod[e[i].y].size; if (nod[e[i].y].size>nod[nod[k].son].size) nod[k].son=e[i].y; } } void dfs2(int k,int start){ nod[k].top=start; if (nod[k].son) dfs2(nod[k].son,start); for (int i=lin[k];i;i=e[i].next) if (e[i].y^nod[k].son&&e[i].y^nod[k].dad) dfs2(e[i].y,e[i].y); } int LCA(int u,int v){ while (nod[u].top^nod[v].top) if (nod[nod[u].top].deep>nod[nod[v].top].deep) u=nod[nod[u].top].dad; else v=nod[nod[v].top].dad; return nod[u].deep<nod[v].deep?u:v; }