• 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

  • 相关阅读:
    Oracle数据库不能使用索引的原因定位
    C语言中的strncmp
    C标准库函数
    C语言字符串函数大全
    Postgres性能检测
    test cert by python
    如何在C语言中巧用正则表达式
    北大软微一年ABCD
    C 语言字符数组的定义与初始化
    25个设计设计灵感的紫色网站案例
  • 原文地址:https://www.cnblogs.com/mzh2017/p/7898896.html
Copyright © 2020-2023  润新知