• 强连通分量(模板)


    对图深度优先搜索,定义DFS(u)为u在搜索树(以下简称为树)中被遍历到的次序号。定义Low(u)为u或u的子树中能通过非父子边追溯到的最早的节点,即DFS序号最小的节点。根据定义,则有:

    Low(u)=Min{DFS(u)DFS(v) (u,v)为后向边(返祖边) 等价于 DFS(v)<DFS(u)且v不为u的父亲节点Low(v) (u,v)为树枝边(父子边)}


    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define MOD 100000
    #define inf 1<<29
    #define LL long long
    #define MAXN 20010
    #define MAXM 50010
    using namespace std;
    struct Edge
    {
        int to,next;
    } edge[MAXM*2];
    int head[MAXM*2],tot;
    int low[MAXN],DFN[MAXN],belong[MAXN];///belong 的值为1-scc
    int index,top;
    int scc ;  ///强连通分量
    bool inStack[MAXN];
    int num[MAXN],stack[MAXN]; ///num为各个强连通分量包含的点的个数,数组编号1-scc  num数组不一定需要,结合实际情况
    
    void addedge(int u,int v)
    {
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++ ;
    }
    
    void Tarjan(int u)
    {
        int v;
        low[u] = DFN[u] = ++index;
        stack[top++] = u;
        inStack[u] = true;
        for(int i=head[u] ; i!=-1 ; i=edge[i].next)
        {
            v = edge[i].to;
            if( !DFN[v] )
            {
                Tarjan(v);
                if(low[u]>low[v])
                    low[u] = low[v];
            }
            else if( inStack[v] && low[u] > DFN[v])
                low[u] = DFN[v];
        }
        if(low[u] == DFN[u])
        {
            scc++;
            do
            {
                v=stack[--top];  ///清空当前强连通分量栈 必须清空
                inStack[v] = false;
                belong[v]=scc;
                num[scc]++;
            }
            while(v!=u);
    
        }
    }
    
    void solve(int N)
    {
        for(int i=1; i<=N ; i++)
        {
            if( !DFN[i] )
                Tarjan(i);
        }
    }
    void init()  ///如果数组太大没必要全部初始化
    {
        tot =  index = scc = top =0;
        memset(DFN,0,sizeof(DFN));
        memset(inStack,false,sizeof(inStack));
        memset(num,0,sizeof(num));
        memset(head,-1,sizeof(head));
    }
    
    int main ()
    {
        int n,m,Case=1;
        while(~scanf("%d%d",&n,&m))
        {
            int u,v;
            init();
            for(int i=0; i<m; i++)
            {
                scanf("%d%d",&u,&v);
                addedge(u,v);
               // addedge(v,u);
            }
            solve(n);
            printf("强连通分量为:%d
    ",scc);
        }
        return 0;
    }
    



  • 相关阅读:
    打造自己的LINQ Provider(上):Expression Tree揭秘
    asp.net MVC 开篇
    .net面试基础
    asp.net MVC3.0
    数字万用表的四位半,三位半都是什么意思?
    lpsz,sz, 变量的命名规范
    老毛桃PE系统安装篡改主页3456.com和强制安装绿色浏览器lvseie.exe
    PC电源厂商及品牌篇(台厂及国际品牌篇)(第二版)
    Borland C++ 语法摘要
    Win8打开文件夹卡顿
  • 原文地址:https://www.cnblogs.com/zswbky/p/5432192.html
Copyright © 2020-2023  润新知