tarjan模板

tarjan 求强连通分量

#include<vector>
#include<cstdio>
#include<iostream>
using namespace std;
vector<int> hh[10000];
struct tonod{
    int p,next;
}g[1000],v[10000];
int top=1,time=0,st[10000],top2=0,num=0;
int dfn[10000],low[10000];
bool inst[10000];
int insert(int x,int y)
{
    v[top].p=y;
    v[top].next=g[x].next;
    g[x].next=top;
    top++;
}
void tarjan(int u)
{
    time++;
    dfn[u]=time;
    low[u]=time;
    st[++top2]=u;
    inst[u]=1;
    for(int i=g[u].next;i!=-1;i=v[i].next)
    {
        int t=v[i].p;
        if(!dfn[t])
        { 
            tarjan(t);
            low[u]=min(low[u],low[t]);
        }
        else
        if(inst[t])
        low[u]=min(low[u],dfn[t]);
    }
    if(dfn[u]==low[u])
    {
        int k;
        num++;
        do
        {
            k=st[top2--];
            hh[num].push_back(k);
            inst[k]=0;
        }
        while(k!=u);
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    g[i].next=-1;
    for(int i=1;i<=m;i++)
    { 
        int a,b;
        scanf("%d%d",&a,&b);
        insert(a,b);
    }
    tarjan(1);
    for(int i=1;i<=num;i++)
    { 
        printf("(");
        for(int j=0;j<hh[i].size()-1;j++)
        printf("%d,",hh[i][j]);
        printf("%d",hh[i][hh[i].size()-1]);
        printf(")
");
    }
}
View Code

tarjan求无向图割边

当且仅当dfn[u]<low[v] 时,边<u,v>为割边

注意更新low时判断v是否是u的父亲,如果是则不更新low

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct tonod{
    int p,next;
}g[1000],v[1000];
struct nn{
    int a,b;
}ans[10000];
bool w[1000][1000];
int top=1,time1=0,num=0;
int dfn[1000],low[1000];
int insert(int x,int y)
{
    v[top].next=g[x].next;
    v[top].p=y;
    g[x].next=top;
    top++;
}
void tarjan(int u,int a)
{
    time1++;
    dfn[a]=time1;
    low[a]=time1;
    for(int i=g[a].next;i!=-1;i=v[i].next)
    {
        int t=v[i].p;
        if(!dfn[t])
        {
            tarjan(a,t);
            low[a]=min(low[a],low[t]);
            if(dfn[a]<low[t])
            {
                int ansa=min(a,t);
                int ansb=max(a,t);
                if(!w[ansa][ansb])
                {
                    ans[++num].a=ansa;
                    ans[num].b=ansb;
                    w[ansa][ansb]=1;
                }
            }
        }
        else
        if(t!=u)
        low[a]=min(low[a],dfn[t]);
    }
}
bool cmp(nn x,nn y)
{
    if(x.a==y.a)
    return x.b<y.b;
    return x.a<y.a;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    g[i].next=-1;
    for(int i=1;i<=m;i++)
    { 
        int a,b;
        scanf("%d%d",&a,&b);
        insert(a,b);
        insert(b,a);
    }
    tarjan(0,1);
    sort(ans+1,ans+num+1,cmp);
    for(int i=1;i<=num;i++)
    printf("%d %d
",ans[i].a,ans[i].b);
}
View Code

 tarjan求无向图割点

1.当dfn[u]<=low[v]时,点u为割点

2.当根节点有两个以上子树时,根节点为割点

同样注意更新low时判断v是否是u的父亲,如果是则不更新low

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 struct tonod{
 6     int p,next;
 7 }v[1000000];
 8 int head[1000000],dfn[1000000],low[1000000];
 9 int top=1,n,m,mytime=0;
10 bool visit[1000000];
11 int ans[1000000],num=0;
12 void set()
13 {
14     for(int i=1;i<=n;i++)
15     head[i]=-1;
16 }
17 void insert(int x,int y)
18 {
19     v[top].next=head[x];
20     v[top].p=y;
21     head[x]=top;
22     top++;
23 }
24 void tarjan(int f,int u)
25 {
26     mytime++;
27     dfn[u]=mytime;low[u]=mytime;
28     int children=0;
29     for(int i=head[u];i!=-1;i=v[i].next)
30     {
31         int t=v[i].p;
32         if(dfn[t]==0)
33         {
34             children++;
35             tarjan(u,t);
36             low[u]=min(low[u],low[t]);
37             if(u!=1&&dfn[u]<=low[t]&&visit[u]==0)
38             {
39                 num++;
40                 ans[num]=u;
41                 visit[u]=1;
42             }
43         }
44         else
45         if(t!=f)
46         low[u]=min(dfn[t],low[u]);
47     }
48     if(u==1&&children>=2)
49     {
50         num++;
51         ans[num]=1;
52     }
53 }
54 void init()
55 {
56     scanf("%d",&n);
57     set();
58     int a,b;
59     while(scanf("%d%d",&a,&b)!=EOF)
60     {
61         insert(a,b);
62         insert(b,a);
63     }        
64 }
65 void outit()
66 {
67     printf("%d
",num);
68     sort(ans+1,ans+num+1);
69     for(int i=1;i<=num;i++)
70     printf("%d
",ans[i]);
71 }
72 int main()
73 {
74     init();
75     tarjan(0,1);
76     outit();
77 } 
View Code

原文地址:https://www.cnblogs.com/mzh2017/p/7898896.html