LCA最近公共祖先——tarjan算法

tarjan算法求最近公共祖先,理論詳見http://www.nocow.cn/


#include <iostream>
#include <fstream>
using namespace std;
/**
    LCA 最近公共祖先 tarjan算法
    並查集+dfs
    離線算法 先讀入所有查詢問題,並不按順序給出結果。
    算法流程
    I.  vis[i]記錄節點i是否被訪問。
        首先進行dfs,tarjan(i)。
        置vis[i] = 1,father[i] = i。
    II. 對所有與節點i有關的查詢(i,j)進行查詢處理
        若節點已經訪問了,vis[j] == 1,則可以找到(i,j)的LCA。
        LCA(i,j) = getfather(j)。
    III.對所有節點i的兒子j,若vis[j] == 0
        則tarjan(j);
        且father[j] = i;
**/
int vis[100],adj[100][100],n,m,q,father[100],que[100][100],anc[100][100];
long adj_len[100],que_len[100];
long find(long i)
{
    if(father[i] == i) return i;
    else return find(father[i]);
}
void tarjan(long i)
{
    long j;
    vis[i] = 1;
    father[i] = i;
    /**先處理與i有關的查詢**/
    for(j=1;j<=que_len[i];j++)
        if(vis[que[i][j]] == 1)
        {
            anc[i][que[i][j]] = find(que[i][j]);
            cout<<i<<" "<<que[i][j]<<" "<<anc[i][que[i][j]]<<endl;
        }
    /**再處理i的所有兒子**/
    for(j=1;j<=adj_len[i];j++)
        if(vis[adj[i][j]] == 0)
        {
            tarjan(adj[i][j]);
            father[adj[i][j]] = father[i];          /**此處要更新father[j]!!!**/
        }
    return;
}
int main()
{
    ifstream fin("d.in");
    long i,j,k,t;
    fin>>n;
    memset(adj_len,0,sizeof(adj_len));
    memset(adj,0,sizeof(adj));
    memset(que_len,0,sizeof(que_len));
    memset(que,0,sizeof(que));

    for(i=1;i<=n;i++)
    {
        fin>>m>>k;
        for(j=1;j<=k;j++)
        {
            fin>>t;
            adj[m][++adj_len[m]] = t;
        }
    }
    fin>>q;
    for(i=1;i<=q;i++)
    {
        fin>>j>>k;
        que[j][++que_len[j]] = k;
        que[k][++que_len[k]] = j;
    }

    tarjan(1);

    cout<<"end";
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章