zoukankan      html  css  js  c++  java
  • 各色Tarjan集合

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100000,M=200000;
    //所有Tarjan都要:
    // dfn[N],low[N],cnt=1,st,scc,zhan[N],top,前向星,vector<int>SCC[N]
    //强连通 ,belong[N],inq[N]
    //割边,边双 bridge[N], belong[N]
    //点双,割点 cut[N],root
    int dfn[N],low[N],cnt=1,zhan[N],top,st,belong[N],scc,head[N],root,n;
    bool bridge[M],inq[N],cut[N];
    vector <int>SCC[N];
    struct bian
    {
        int nxt,to;
    }b[M];
    void add(int from,int to)
    {
        b[++cnt].nxt=head[from];
        b[cnt].to=to;
        head[from]=cnt;
    }
    void Tarjan1(int cur)//强连通
    {
        dfn[cur]=low[cur]=++st;
        zhan[++top]=cur;inq[cur]=true;
        int i=head[cur],v;
        while(i!=0)
        {
            v=b[i].to;
            if(dfn[v]==0)
            {
                Tarjan1(v);
                low[cur]=min(low[cur],low[v]);
            }
            else
            {
                if(inq[v]==true)
                {
                    low[cur]=min(low[cur],dfn[v]);
                }
            }    
            i=b[i].nxt;
        }
        if(low[cur]==dfn[cur])
        {
            scc++;
            int ding;
            do
            {
                ding=zhan[top];
                inq[ding]=false;
                zhan[top--]=0;
                belong[ding]=scc;
                SCC[scc].push_back(ding);
            }while(ding!=cur);
        }
    }
    void Tarjan2(int cur,int pre)//割边,边双 
    {
        dfn[cur]=low[cur]=++st;
        zhan[++top]=cur;
        int i=head[cur],v;
        while(i!=0)
        {
            v=b[i].to;
            if(i!=pre)
            {
                if(dfn[v]==0)
                {
                    Tarjan2(v,i^1);
                    low[cur]=min(low[cur],low[v]);
                    if(low[v]>dfn[cur])
                    {
                        bridge[i]=bridge[i^1]=true;
                        scc++;
                        int ding;
                        do
                        {
                            ding=zhan[top];
                            zhan[top--]=0;
                            belong[ding]=scc;
                            SCC[scc].push_back(ding);
                        }while(ding!=v);
                    }
                }
                else
                    low[cur]=min(low[cur],dfn[v]);
            }
            i=b[i].nxt;
        }
    }
    void Tarjan3(int cur)
    {
        dfn[cur]=low[cur]=++st;
        zhan[++top]=cur;
        int i=head[cur],v,child=0;
        while(i!=0)
        {
            v=b[i].to;
            if(dfn[v]==0)
            {
                child++;
                Tarjan3(v);
                low[cur]=min(low[cur],low[v]);
                if(low[v]>=dfn[cur])
                {
                    if(root!=cur)
                        cut[cur]=true;    
                    scc++;
                    int ding;
                    do
                    {
                        ding=zhan[top];
                        zhan[top--]=0;
                        SCC[scc].push_back(ding);
                    }while(ding!=v);
                    SCC[scc].push_back(cur);
                }
            }
            else
                low[cur]=min(low[cur],dfn[v]);
            i=b[i].nxt;
        }
        if(cur==root&&child>=2)
        {
            cut[cur]=true;
        }
    }
    int main()
    {
        for(int i=1;i<=n;i++)
        {
            if(dfn[i]==0)
                Tarjan1(i);
            if(dfn[i]==0)
            {
                Tarjan2(i,0);
                int ding; 
                while(top>0)
                {
                    ding=zhan[top];
                    zhan[top--]=0;
                    SCC[scc].push_back(ding);
                }
            }
            if(dfn[i]==0)
                root=i,Tarjan3(i);
        }
        return 0;
    }

    特殊点:
    强连通的出栈在函数末,进入条件low[cur]=dfn[cur],break条件ding!=cur,注意要维护是否在栈中的数组inq,dfn[v]!=0且inq[v]==true时,才能进入else语句中更新low[cur];

    边双和割边出栈在Tarjan过程中的dfn[v]=0中,判断是low[v]>dfn[cur],break条件ding!=v,结束后要清栈;

    割点和点双联通在Tarjan过程中的dfn[v]=0中,判断是low[v]>=dfn[cur],break条件ding!=v,注意求割点时,若cur=root且child>=2,为割点;

  • 相关阅读:
    web前端开发常用链接
    Restful API 设计原则
    web最佳实践
    MySQL 命令
    Mac MySQL安装
    IntelliJ IDEA 创建Maven项目及tomcat配置
    Mac安装和配置Maven
    Mac安装和配置Tomcat
    IntelliJ IDEA 创建java项目及字体设置
    Java-GUI
  • 原文地址:https://www.cnblogs.com/HKHbest/p/13922912.html
Copyright © 2011-2022 走看看