其他分享
首页 > 其他分享> > Tarjan

Tarjan

作者:互联网

Robert E. Tarjan(罗伯特·塔扬,1948~),生于美国加州波莫纳,计算机科学家。
Tarjan 发明了很多算法和数据结构。不少他发明的算法都以他的名字命名,以至于有时会让人混淆几种不同的算法。比如求各种连通分量的 Tarjan 算法,求 LCA(Lowest Common Ancestor,最近公共祖先)的 Tarjan 算法。并查集、Splay、Toptree 也是 Tarjan 发明的。

在无向连通图中,如果将其中一个点以及所有连接该点的边去掉,图就不再连通,那么这个点就叫做割点(cut vertex / articulation point)。

image

  1. 对一个连通图进行DFS,在DFS的过程中如果存在一个非根点不存在返祖边(不能回到父节点之前的点),则该节点的父节点便为割点。
  2. 对于根节点若存在两个及以上的子树,那么它就是割点
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4 +5,M = 2e5 + 5;
int h[N],ne[M],e[M],idx;
int dfn[N],low[N],n,m,root,tim;
bool cnt[N];
void add(int x,int y)
{
    e[++idx] = y,ne[idx] = h[x],h[x] = idx;
}
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void Tarjan(int x)
{
    dfn[x] = low[x] = ++ tim;//记录时间截
    int flag = 0;
    for(int i = h[x] ;i; i = ne[i])
    {
        int y = e[i];
        if(!dfn[y])
        {
            Tarjan(y);
            low[x] = min(low[x],low[y]);
            if(low[y] >= dfn[x])//它能到的边的最小祖先大于它的dfs序
            {
                flag ++ ;
                if(x != root || flag > 1)
                {
                    cnt[x] = 1;
                }
            }

        }
        else
        low[x] = min(low[x],dfn[y]);

    } 
}


int main()
{
    n = read();
    m = read();
    for(int x,y,i = 1 ; i <= m ; i ++)
    {
        x = read();
        y = read();
        if(x == y)continue;
        add(x,y),add(y,x);
    }

    for(int i =  1 ; i <= n  ;i ++ )
    {
        if(!dfn[i])
        {
            root  = i;
            Tarjan(i);
        }
    }
    int res = 0;
    for(int i = 1 ; i <= n ; i ++ )
    if(cnt[i])res ++ ;
    printf("%d\n",res);
    for(int i = 1 ; i <= n ; i ++ )
    if(cnt[i])printf("%d ",i);

}

标签:Tarjan,ch,idx,int,算法,节点
来源: https://www.cnblogs.com/ErFu/p/16491058.html