码迷,mamicode.com
首页 > 编程语言 > 详细

最近公共祖先 tarjan离线算法 C++

时间:2015-04-26 15:12:34      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

最近做到一道题目,大概的意思就是求一个多叉树中两个节点的最近公共祖先,输入是用邻接矩阵表示的。

要想理解tarjan算法并实现它,需要先理解一下内容:

1) 深度优先搜索;tarjan算法核心思想:当某节点刚刚搜索完毕时,看与其相关的结点v是否已经被访问,如果v已经被访问过了,则它们的最近公共祖先就是v的祖先。

2) 并查集原理和实现方法,并查集的代表和祖先的区别(其实也可以一起表示),祖先的更新时刻

3) 如何表示多叉数(邻接链表,邻接矩阵),如何表示查询对,如何记录查询结果

下面是c++实现代码,比较偷懒,每次调用函数就查询一个。查询对的数据结构可以用下面提到的邻接表来表示。

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;


class lca{
public:
    lca(const vector<string> &vstr) 
        :str(vstr),f(vstr.size(),-1),ancestor(vstr.size(),-1),visit(vstr.size(),0) { }
    int lca_query(int vertex,int u, int v){
        static int ans=-1;
        ancestor[vertex] = vertex;
        visit[vertex] = true;
        for (int i = 0; i < str.size(); ++i){
            if ((str[vertex][i] == 1) && (visit[i] == 0)){
                ans=lca_query(i, u, v);
                unite(vertex, i);
                ancestor[find(vertex)] = vertex;
            }
        }
        if (vertex == u&&visit[v])
            ans = ancestor[find(v)];
        if (vertex == v&&visit[u])
            ans = ancestor[find(u)];
        return ans;
    }
private:
    const vector<string> &str;
    vector<int> f;  //并查集
    vector<int> ancestor;
    vector<bool> visit;
    int find(int i)
    {
        if (f[i] == -1)
            return i;
        return f[i] = find(f[i]);
    }

    void unite( int u, int v)
    {
        int x = find(u);
        int y = find(v);
        if (x != y)
            f[x] = y;
    }

};



int main(){
    vector<string> v123 = { "01100001", "10011000", "10000000", "01000000", "01000110","00001000","00000100","10000000" };
    lca query1(v123);
    cout << query1.lca_query(0,4, 7);

}

 

 

实际上用邻接矩阵来表示多叉数是很浪费时间的,单颗多叉树作为无环图,只有(n-1)条边,这里n是节点数。网上有很好的方法来表示邻接链表,

struct Edge
{
    int to, next;
}edge[maxn * 2];
int head[maxn], tot;
void addedge(int u, int v)//邻接表头插法加边
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

本质上就是一个单链表,不过这个单链表的next指针只是一个数组下标值。head[u]记录的是上一次从u出发的边的数组下边。

要理解tarjan算法,得先理解并查集

 

最近公共祖先 tarjan离线算法 C++

标签:

原文地址:http://www.cnblogs.com/Nastukashii/p/4457713.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!