zoukankan      html  css  js  c++  java
  • Tarjan算法

      做了几道题之后才发现Tarjan写了这么多牛逼的算法。

      目前我所学的Tarjan经常用的算法主要就两个:

      1.Tarjan算法求连通量.

      2.Tarjan离线算法求CLA ( Cloest common ancestor)

      第一种比较好理解,第二种就不那么好理解了。

      推荐两个写的比较好的博客:

      1.http://alanyume.com/130.html

      2.http://www.cnblogs.com/jackge/archive/2013/05/10/3071437.html

      Tarjan离线算法的核心就是 DFS 和 并查集 。通过DFS不断将下面的点不断向上合并,在利用DFS的特性,find_set(u)的时候得到的结果就刚好是Cloest Common Ancestor了。

    例题:

    H - Closest Common Ancestors
    Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u
    Appoint description:
     

    Description

    Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest common ancestor of two nodes u and v is the node w that is an ancestor of both u and v and has the greatest depth in the tree. A node can be its own ancestor (for example in Figure 1 the ancestors of node 2 are 2 and 5)

    Input

    The data set, which is read from a the std input, starts with the tree description, in the form:

    nr_of_vertices
    vertex:(nr_of_successors) successor1 successor2 ... successorn
    ...
    where vertices are represented as integers from 1 to n ( n <= 900 ). The tree description is followed by a list of pairs of vertices, in the form:
    nr_of_pairs
    (u v) (x y) ...

    The input file contents several data sets (at least one).
    Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.

    Output

    For each common ancestor the program prints the ancestor and the number of pair for which it is an ancestor. The results are printed on the standard output on separate lines, in to the ascending order of the vertices, in the format: ancestor:times
    For example, for the following tree:

    Sample Input

    5
    5:(3) 1 4 2
    1:(0)
    4:(0)
    2:(1) 3
    3:(0)
    6
    (1 5) (1 4) (4 2)
          (2 3)
    (1 3) (4 3)

    Sample Output

    2:1
    5:5

    Hint

    Huge input, scanf is recommended.
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<iomanip>
    #include<queue>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long LL;
    const int maxN = 1100;
    int n, m;
    int fa[maxN], head[maxN], vis[maxN], ans[maxN];
    vector<int> edge[maxN];
    int query[maxN][maxN];
    
    void init(){
        memset(fa, 0, sizeof(fa));
        memset(head, 0, sizeof(head));
        memset(vis, 0, sizeof(vis));
        memset(ans, 0, sizeof(ans));
        memset(query, 0, sizeof(query));
        for(int i=0 ; i<n; ++i) edge[i].clear();
    }
    
    int find_set(int u){
        if(u == fa[u])  return fa[u];
        return fa[u] = find_set(fa[u]);
    }
    
    void LCA(int u){
        fa[u] = u;
        for(int i=0 ; i<edge[u].size(); ++i){
            LCA(edge[u][i]);
            fa[edge[u][i]] = u;
        }
        vis[u] = 1;
        for(int i=1 ; i<=n;++i){
            if(query[u][i] && vis[i]){
                ans[find_set(i)] += query[u][i];
            }
        }
    }
    
    
    int main(){
        while(scanf("%d", &n)!=EOF){
            init();
            for(int i=1 ; i<=n; ++i){
                int a, b;
                scanf("%d:(%d)", &a, &b); //注意输入部分
                for(int j=0 ; j<b ; ++j){
                    int f;
                    scanf(" %d", &f);
                    head[f] = 1;
                    edge[a].push_back(f);
                }
            }
            scanf(" %d", &m);
            for(int i=0 ; i<m; ++i){
                int a, b;
                scanf(" (%d %d)", &a, &b);//注意输入部分
                query[a][b]++;
                query[b][a]++;
            }
            int start = 0;
            for(int i=1 ; i<=n; ++i){
                if(head[i]!= 1) start = i;
            }
            LCA(start);
            for(int i=1 ; i<=n; ++i){
                if(ans[i])  printf("%d:%d
    ", i, ans[i]);
            }
        }
        return 0;
    }

     

  • 相关阅读:
    架构师考试回顾
    精通 WPF UI Virtualization
    疑难杂症之Web客户端无法登录
    CDTray, 打开,关闭光驱的系统托盘程序
    原来Queryable是这样实现的..
    jQuery.Excel, 使用Ctrl+方向键/Home/End在input表格中移动
    nGoodPersonCards++
    C#数据库数据导入导出系列之三 数据库导出到Excel下
    调用webservice时提示对操作的回复消息正文进行反序列化时出错&&Web service 超过了最大请求长度
    ASP.NET网络映射驱动器无权限访问的解决方案(转)
  • 原文地址:https://www.cnblogs.com/topW2W/p/5240645.html
Copyright © 2011-2022 走看看