圖論 LCA在線算法 倍增法

Lowest Common Ancestor:

如求A,B兩點的LCA,先計算出各個結點的深度depth[],然後,通過遞推公式求出各個結點的2次方倍的祖先ancestor[],假設depth[A] > depth[B],則找到depth[ancestor[A][i]] == depth[B]也就是A的某一祖先與B深度相同,然後,u = ancestor[A][i],通過ancestor[u][i] 與ancestor[B][i]比較找出LCA。

(ancestor[a][b] 表示與a的距離爲2^b的祖先,則ancestor[a][0]表示爲a的父親。如 a->b->c->d->e,a爲根, 則ancestor[e][2] 爲a)

遞推公式:ancestor[a][b] = ancestor[ancestor[a][b - 1]][b - 1]

Template:

#define NODE_SIZE 10010
#define ANC_SIZE 15
// ANC_SIZE = Log(2, NODE_SIZE)
int ancestors[NODE_SIZE][ANC_SIZE];
int depth[NODE_SIZE];

vector<int> childs[NODE_SIZE];

int LCAncestor(int u, int v) {
    if (depth[u] < depth[v]) { swap(u, v); }
    for (int i = ANC_SIZE ; i >= 0 ; --i) {
        if (depth[ancestors[u][i]] >= depth[v] ) {
            u = ancestors[u][i];
            if (depth[u] == depth[v]) { break; }
        }
    }
    if (u == v) { return u; }

    for (int i = ANC_SIZE - 1; i >= 0 ; --i) {
        if (ancestors[u][i] != ancestors[v][i]) {
            u = ancestors[u][i]; 
            v = ancestors[v][i];
        }
    }

    return ancestors[u][0];
}
void GetDepth(int rt, int dep) {
    depth[rt] = dep;
    for (int i = 0 ; i < childs[rt].size(); ++i) {
        GetDepth(childs[rt][i], dep + 1);
    }
}


GetDepth(root, 1);
for (int i = 1; i < ANC_SIZE ; ++i) {
    for (int j = 1 ; j <= n ; ++j) {
        ancestors[j][i] = ancestors[ancestors[j][i - 1]][i - 1];
    }
}
printf("%d\n", LCAncestor(u, v));


發佈了69 篇原創文章 · 獲贊 4 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章