1. 程式人生 > >求LCA(最近公共祖先)

求LCA(最近公共祖先)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <vector>
using namespace std;
const int MAXN = 10010;
int rmq[2*MAXN];//rmq陣列,就是尤拉序列對應的深度序列
struct ST {
    int mm[2*MAXN];
    int dp[2*MAXN][20];//最小值對應的下標
    void init(int n) {
        mm[0] = -1;
        for(int i = 1; i <= n; i++) {
            mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
            dp[i][0] = i;
        }
        for(int j = 1; j <= mm[n]; j++)
            for(int i = 1; i + (1<<j) - 1 <= n; i++)
                dp[i][j] = rmq[dp[i][j-1]] <
                           rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
    }
    int query(int a,int b) { //查詢[a,b]之間最小值的下標
        if(a > b)swap(a,b);
        int k = mm[b-a+1];
        return rmq[dp[a][k]] <=
               rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
    }
};
vector<int> G[MAXN];
int F[MAXN*2];//尤拉序列,就是dfs遍歷的順序,長度為2*n-1,下標從1開始
int P[MAXN];//P[i]表示點i在F中第一次出現的位置
int cnt;
ST st;
void dfs(int u,int pre,int dep) {
    F[++cnt] = u;
    rmq[cnt] = dep;
    P[u] = cnt;
    for(int i=0; i<G[u].size(); i++) {
        int v = G[u][i];
        if(v == pre)continue;
        dfs(v,u,dep+1);
        F[++cnt] = u;
        rmq[cnt] = dep;
    }
}
void LCA_init(int root,int n) { //查詢LCA前的初始化
    cnt = 0;
    dfs(root,root,0);
    st.init(2*n-1);
}
int query_lca(int u,int v) { //查詢u,v的lca編號
    return F[st.query(P[u],P[v])];
}
int main() {
    for(int i=0; i<10; i++)
        G[i].clear();
    G[1].push_back(2);
    G[2].push_back(1);
    G[1].push_back(3);
    G[3].push_back(1);
    G[2].push_back(4);
    G[4].push_back(2);
    G[5].push_back(2);
    G[2].push_back(5);
    G[4].push_back(6);
    G[6].push_back(4);
    LCA_init(1,7);   
    cout<<query_lca(6,6)<<endl;
    return 0;
}

相關推薦

LCA(最近公共祖先)

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <

LCA——最近公共祖先 倍增演算法

LCA是啥呢,LCA就是一棵樹裡兩個節點的最近公共祖先,如下圖 2號節點和3號節點的LCA就是1, 5號節點和11號節點的LCA就是2,8號節點和4號節點的lca就是4 那麼怎麼求LCA呢。首先要建樹,然後最容易想到的就是兩個節點一起向上跳,第一個相遇的節點就是LCA

倍增法Lca(最近公共祖先)

一. 明確問題 看標題便知道了, 這篇部落格力求解決的問題是求出一棵樹的兩個結點的最近公共祖先(LCA), 方法是倍增法. 那麼什麼是Lca呢? 它是一棵樹上兩個結點向上移動, 最後交匯的第一個結點, 也就是說這兩個結點祖先裡離樹根最遠也是離

(轉)Tarjan應用:割點/橋/縮點/強連通分量/雙連通分量/LCA(最近公共祖先)

應用 說明 lca ref father 無向圖 沒有 經理 遠的 本文轉載自:http://hi.baidu.com/lydrainbowcat/item/f8a5ac223e092b52c28d591c 作者提示:在閱讀本文之前,請確保您已經理解並掌握了基本的T

[轉]LCA 最近公共祖先

log 比較 下一步 個人 idt 合並函數 orz ref tle 原文傳送門orzJVxie Tarjan(離線)算法的基本思路及其算法實現     首先是最近公共祖先的概念(什麽是最近公共祖先?):     在一棵沒有環的樹上,每個節點肯定有其父親節點和祖先節點

LCA 最近公共祖先 (模板)

ace memset air size oid int fin vector n) 1 #include <iostream> 2 #include <stdio.h> 3 #include <cstring> 4 #i

[筆記]LCA最近公共祖先---倍增在線算法

targe mdk 在線 com diy href mta 算法 collect 059M37853N虜3Jhttp://www.zcool.com.cn/collection/ZMTg2OTM5ODg=.html 痹o83RI世9EUS兩http://www.zcool

筆記:LCA最近公共祖先 Tarjan(離線)算法

否則 二叉樹 tail [] info enter 父親節 自己 初始 LCA最近公共祖先 Tarjan他賤(離線)算法的基本思路及其算法實現 本文是網絡資料整理或部分轉載或部分原創,參考文章如下: https://www.cnblogs.com/JVxie/p/4

近親結婚之 LCA 最近公共祖先

故事出真知 阿珍 愛上了 阿強 但 被他們的父母 拒絕 了 沒錯 狗血的近親結婚劇情開始了 阿珍 說: 不行,我深深愛著我的阿強,誰也不能把我們分開 阿強 深情地望著阿珍 說 一定會有機會的! 此時 他突然靈機一現 只要不是 三代近親 就可以了!!! 現在 深深相

LCA 最近公共祖先 模板

Lca 離線演算法(tarjan演算法) 模板 #include<bits/stdc++.h> #define _ 1000100 using namespace std; char buf[1<<15],*fs,*ft; inline char getc()

『圖論』LCA最近公共祖先

概述篇 LCA(Least Common Ancestors),即最近公共祖先,是指這樣的一個問題:在一棵有根樹中,找出某兩個節點 u 和 v 最近的公共祖先。 LCA可分為線上演算法與離線演算法 線上演算法:指程式可以以序列化的方式一個一個處理輸入,也就是說在一開始並不需要知道所有的輸入。

LCA 最近公共祖先,樹上兩點距離,線段重合長度

對於LCA的一些理解 RMQ dfs處理樹 對於一個樹形結構,可以用dfs將一顆樹轉化成陣列,陣列中記錄每個點的標號,這樣陣列就按照dfs的順序把樹存了下來 確定祖先的範圍 對於詢問的節點X和Y, X、Y的祖先一定存在於陣列中X、Y第一次出現的區間內,而且祖先就是區

Tarjan離線演算法 (LCA最近公共祖先

Tarjan離線演算法是利用並查集和DFS來達到離線處理的目的 我們都知道,對於一棵樹,後序遍歷一遍,訪問它的根的時機一定是後與它的孩子的。換一句話,當開始遍歷它的根節點的時候,它遍歷過的孩子的公共祖先一定是這個根而這也就成為了我們解題的思想。 由於是需要對

LCA最近公共祖先的離線演算法(Tarjan)和線上演算法(ST)

最近公共祖先簡稱LCA(Lowest Common Ancestors),所謂LCA,是當給定一個有根樹T時,對於任意兩個結點u、v,找到一個離根最遠的結點x,使得x同時是u和v的祖先,x 便是u、

LCA(最近公共祖先)倍增演算法

最近公共祖先有多種演算法 如倍增,RMQ,樹鏈剖分等 這裡先介紹倍增演算法 預處理複雜度nlog(n); 詢問複雜度log(n); 倍增與二進位制息息相關 與分塊的演算法有些相似之處 使用倍增演算法時開一個fa[n][S]陣列 fa[i][j]

LCA 最近公共祖先 tarjan離線 總結 結合3個例題

在網上找了一些對tarjan演算法解釋較好的文章 並加入了自己的理解 LCA(Least Common Ancestor),顧名思義,是指在一棵樹中,距離兩個點最近的兩者的公共節點。也就是說,在兩個點通往根的道路上,肯定會有公共的節點,我們就是要求找到公共的節點中,深

LCA最近公共祖先——Tarjan模板

tar wap 交換 最大 dfs %d scan 公共祖先 class LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根樹中,找出某兩個結點u和v最近的公共祖先。 Tarjan是一種離線算法,時間復雜度O(n+Q),Q表示詢問次數,其

『圖論』LCA 最近公共祖先

## **概述篇** LCA (Least Common Ancestors) ,即最近公共祖先,是指這樣的一個問題:在一棵有根樹中,找出某兩個節點 `u` 和 `v` 最近的公共祖先。 LCA 可分為**線上演算法**與**離線演算法** - **線上演算法:**指程式可以以序列化的方式一個一個

最近公共祖先LCA)的各種算法

host .cn 提取 模擬 最小值 以及 play 樹鏈剖分 pla 水一發題解。 我只是想存一下樹剖LCA的代碼...... 以洛谷上的這個模板為例:P3379 【模板】最近公共祖先(LCA) 1.樸素LCA 就像做模擬題一樣,先dfs找到基本信息:每個節點的父親、深度

最近公共祖先LCA)的三種方法總結(Tarjan/倍增/樹鏈剖分)

以模板題目poj1330為例   Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: