• 【UOJ 92】有向图的强连通分量


    【题目描述】:

    有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。

    现在给出一个有向图。结点个数N(<=1000)(编号1~N),边数M(<=5000)。请你按照从小到大的顺序输出最大的强连通分量结点编号。

    【输入描述】:

    第一行N和M 以下M行,每行两个空格隔开的整数表示一条有向边;

    【输出描述】:

    输出一行,最大的强连通分量的结点(由小到大输出)

    【样例输入】:

    10 20
    2 2
    5 3
    8 5
    3 4
    8 7
    10 10
    10 6
    7 7
    2 8
    3 2
    8 1
    3 8
    1 7
    8 10
    7 5
    6 4
    9 2
    8 6
    7 5
    1 8

    【样例输出】:

    1 2 3 5 7 8

    【时间限制、数据范围及描述】:

    时间:1s 空间:256M

    N<=1000, M<=5000

    tarjan模板如下:

    #include "iostream"
    #include "cstdio"
    #include "cstdlib"
    #include "stack"
    #include "algorithm"
    using namespace std;
    #define MAXN 1005
    #define MAXM 5005
    int n,m;
    
    /*********************** 
           链式前向星 
    ***********************/
    struct ENode{
        int v,w,next;
    }edge[MAXM];    //边集 
    int p[MAXN],ec;    //点集和边集计数 
    void InsertE(int u, int v, int w){    //插入边 
        edge[++ec].v = v; edge[ec].w = w;
        edge[ec].next = p[u];
        p[u] = ec;
    }
    
    /***********************
         Tarjan算法基础 
         搜索强连通分量 
    ***********************/
    int dfn[MAXN],cTime,low[MAXN];    //时间戳,时间戳计数,祖先时间。 
    int gid[MAXN],gc;    // 分量数组,分量计数。 
    bool ins[MAXN]; stack<int> sTar;    //入栈标志,辅助栈 
    void Tarjan(int u){
        dfn[u]=low[u]=++cTime;        //时间戳与祖先时间初始化 
        ins[u]=1; sTar.push(u);    //入栈 
        for(int i=p[u];i;i=edge[i].next){    //递归处理所有子结点 
            int v=edge[i].v;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);    //利用子孙,更新能回指的祖先时间戳 
            }
            else if(ins[v])        //记录U能回指的最早祖先的时间戳 
                low[u]=min(low[u],dfn[v]);
        }
        if(low[u]>=dfn[u]){        //判断U是否分量的根 
            gc++;
            int i;
            do{
                i=sTar.top(); ins[i]=0;
                gid[i]=gc; sTar.pop();    //分量出栈
            }while(i!=u);    //出栈至当前结点,包括当前结点 
        }
    }
    
    int main()
    {
        freopen("connect.in","r",stdin);
        freopen("connect.out","w",stdout);
        int x,y,c=0;
        cin >> n >> m;
        for(int i=0;i<m;i++){
            cin >> x >> y;
            InsertE(x,y,0);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i]) Tarjan(i);
        int a[MAXN]={0};
        for(int i=1;i<=n;i++){
            a[gid[i]]++;
            if(a[gid[i]]>a[a[0]])a[0]=gid[i];
        }
        for(int i=1;i<=n;i++)
            if(gid[i]==a[0])
                cout << i << ' ';
        cout << endl;
        return 0;
    }
  • 相关阅读:
    装饰器和表达生成式
    函数
    字符编码
    函数基础
    列表,字典与集合
    Linux Semaphore
    tp5安装easyWeChat
    wx.request
    小程序设计规范
    小程序的概念和特点
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11139459.html
Copyright © 2020-2023  润新知