美文网首页
构造强连通图

构造强连通图

作者: Gitfan | 来源:发表于2017-08-07 11:45 被阅读0次

    给定一张有向图,最少添加几条边使得有向图成为一个强连通图 ? ?
    以下内容为转载

    将有向图变为强连通图
    ①连通图

    找出所有的强连通分量, 然后缩成一个点,然后统计缩点之后的新图的出度为0的点的个数(记为cntOut),和入度为0的点的个数(记为cntIn)

    那么要加边的条数就是max(cntOut,cntIn)

    这个为什么呢?? 因为,如果一个点的入度为0,那么说明这个点是不可达的,如果一个点的出度为0,那么说明这个点到其它点是不可达的。

    为了解决这个情况,那么只要在出度为0的点(设为u)和入度为0的点之间连一条u-->v的边,那么就解决了这种情况。

    不断的连边,只要一个点问题没解决就要连边, 所以是在两者之间取max

    注意,如果图本来就是强连通图,那么会缩成一个点,它出入度都为0,即max(cntOut,cntIn)=1,但本来不需要连任何边,所以ans=0,ans!=max(cntOut,cntIn),这个要特判

    ②非连通图

    对于每个连通的分支之间,按照上面的方法变成强连通分量。

    至于两个连通分量之间,连一条你指向我的边,再连一条我指向你的边就行了。

    I - Proving Equivalences

    #include <cstdio>
    #include<cstring>
    #include<vector>
    #include<stack>
    #include<set>
    #include<algorithm>
    #include<iterator>
    using namespace std;
    const int MAXN=20010;
    const int MAXE=50010;
    struct Node
    {
        int to,next;
    }edge[MAXE];
    int head[MAXN],cnt;
    void addEdge(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    int low[MAXN],dfn[MAXN],clocks;
    int sccno[MAXN],blocks;
    int in[MAXN],out[MAXN];
    int onStack[MAXN];
    stack<int> sta;
    void DFS(int u)
    {
        low[u]=dfn[u]=++clocks;
        sta.push(u);
        onStack[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dfn[v]==0)
            {
                DFS(v);
                low[u]=min(low[v],low[u]);
            }
            else if(onStack[v]) low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            blocks++;
            while(true)
            {
                int x=sta.top();
                sta.pop();
                onStack[x]=0;
                sccno[x]=blocks;
                if(x==u) break;
            }
        }
    }
    void work(int n)
    {
        memset(dfn,0,sizeof(dfn));
        memset(sccno,0,sizeof(sccno));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(onStack,0,sizeof(onStack));
        blocks=clocks=0;
        for(int i=1;i<=n;i++)
        {
            if(dfn[i]==0) DFS(i);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j!=-1;j=edge[j].next)
            {
                if(sccno[i]!=sccno[edge[j].to])
                {
                    in[sccno[edge[j].to]]++;
                    out[sccno[i]]++;
                }
            }
        }
        if(blocks==1)
        {
            printf("0\n");
            return;
        }
        int inZero=0,outZero=0;
        for(int i=1;i<=blocks;i++)
        {
            if(in[i]==0) inZero++;
            if(out[i]==0) outZero++;
        }
        printf("%d\n",max(inZero,outZero));
    }
    int main()
    {
        int n,m,a,b,t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            memset(head,-1,sizeof(head));
            cnt=0;
            for(int i=0;i<m;i++)
            {
                scanf("%d%d",&a,&b);
                addEdge(a,b);
            }
            work(n);
        }
    }
    

    相关文章

      网友评论

          本文标题:构造强连通图

          本文链接:https://www.haomeiwen.com/subject/xqholxtx.html