图的Tarjan算法

“Tarjan有三种算法 你们知道吗”——Tar乙己

void tarjan(int x)
{
    low[x]=dfn[x]=++ind;
    q[++top]=x;mark[x]=1;
    for(int i=last[x];i;i=e[i].next)
        if(!dfn[e[i].to])
        {
            tarjan(e[i].to);
            low[x]=min(low[x],low[e[i].to]);
        }
        else if(mark[e[i].to])
            low[x]=min(low[x],dfn[e[i].to]);
    if(low[x]==dfn[x])
    {
        int now=0;scc++;
        while(now!=x)
        {
            now=q[top--];mark[now]=0;
            bl[now]=scc;num[scc]++;
        }
    }
}
缩点
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack> 
#include<vector> 
using namespace std;
const int maxn=50010;
int first[maxn],to[maxn],next[maxn],cnt,from[maxn];
void add(int u,int v)
{
    from[++cnt]=u;
    to[cnt]=v;
    next[cnt]=first[u];
    first[u]=cnt;
}
int dfn[maxn],low[maxn],vis[maxn],ind,scc,now,st[maxn],top;
int isc[maxn];
vector<int> bl[maxn];
int blc;
int tag[maxn];
void Tarjan_dfs(int x,int fa)
{
    int son=0;
    low[x]=dfn[x]=++ind;
    for(int i=first[x];i;i=next[i])
    {
        int now=to[i];
        if(!dfn[now])
        {
            st[++top]=i;son++;
            Tarjan_dfs(now,x);
            low[x]=min(low[x],low[now]);
            if(low[now]>=dfn[x])
            {
                isc[x]=1;
                bl[++blc].clear();
                while(1)
                {
                    int num=st[top--];
                    if(tag[from[num]]!=blc)
                    {
                        bl[blc].push_back(from[num]);
                        tag[from[num]]=blc;
                    }
                    if(tag[to[num]]!=blc)
                    {
                        bl[blc].push_back(to[num]);
                        tag[to[num]]=blc;
                    }
                    if(to[num]==now && from[num]==x)break;
                }
            }
        }
        else if(dfn[now]<dfn[x] && now!=fa)
        {
            st[++top]=i;
            low[x]=min(low[x],dfn[now]);
        }
    }
    if(fa==0 && son==1)isc[x]=0;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    for(int i=1;i<=n;i++)if(!dfn[i])Tarjan_dfs(i,-1);
    cout<<blc<<endl;
    return 0;
}
点双连通分量
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack> 
#include<vector> 
using namespace std;
const int maxn=50010;
int first[maxn],to[maxn],next[maxn],cnt,from[maxn];
void add(int u,int v)
{
    from[++cnt]=u;
    to[cnt]=v;
    next[cnt]=first[u];
    first[u]=cnt;
}
int dfn[maxn],low[maxn],vis[maxn],ind,scc,now,st[maxn],top;
int isb[maxn];
vector<int> bl[maxn];
int blc;
int tag[maxn];
void Tarjan_dfs(int x,int fa)
{
    dfn[x]=low[x]=++ind;
    for(int i=first[x];i;i=next[i])
    {
        int v=to[i];
        if(!dfn[v])
        {
            Tarjan_dfs(v,x);
            low[x]=min(low[x],low[v]);
            if(low[v]>dfn[x])
                isb[i]=isb[i^1]=1;
        }
        else if(dfn[v]<dfn[x] && v!=fa)low[x]=min(low[x],dfn[v]);
    }
}
int vis[maxn];
void dfs(int x)
{
    vis[x]=1;
    tag[x]=blc;
    for(int i=first[x];i;i=next[i])
    {
        int v=to[i];
        if(isb[v])continue;
        if(!vis[i])dfs(v);
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    for(int i=1;i<=n;i++)if(!dfn[i])Tarjan_dfs(i,-1);
    for(int i=1;i<=n;i++)if(!vis[i]){blc++;dfs(i);}
    cout<<blc<<endl;
    return 0;
}
边双连通分量
原文地址:https://www.cnblogs.com/Kong-Ruo/p/7761631.html