强连通分量(LRJ训练指南)

#include <iostream>

#include <queue>

#include <string>

#include <cstdio>

#include <cstring>

#include <vector>

#include <stack>

#include <algorithm>

using namespace std;

const int maxn = 10000;

int gn, gm;



vector<int> gg[maxn];

int pre[maxn], low[maxn], sccno[maxn], dfs_clock, scc_cnt;



stack<int> gs;



void dfs(int u) {

    int i;

    pre[u] = low[u] = ++dfs_clock;

    gs.push(u);

    for(i = 0; i < (int)gg[u].size(); i++) {

        int v = gg[u][i];

        if(!pre[v]) {

            dfs(v);

            low[u] = min(low[u], low[v]);

        }

        else if(!sccno[v]) {

            low[u] = min(low[u], low[v]);//min(low[u], low[v]);

        }

    }

    if(low[u] == pre[u]) {

        scc_cnt++;

        for(;;) {

            int x = gs.top();

            gs.pop();

            sccno[x] = scc_cnt;

            if(x == u) break;

        }

    }

}



void find_scc(int n) {

    dfs_clock = scc_cnt = 0;

    memset(sccno, 0, sizeof(sccno));

    memset(pre, 0, sizeof(pre));

    for(int i = 1; i <= n; i++) {

        if(!pre[i]) dfs(i);

    }

}



void print() {

    for(int i = 1; i <= gn; i++) {

        printf("i = %d -> %d\n", i, sccno[i]);

    }

}



int main()

{

    int from, to;

    while(scanf("%d%d", &gn, &gm) ==2) {

        for(int i = 0; i < gm; i++) {

            scanf("%d%d", &from, &to);

            gg[from].push_back(to);

        }

        find_scc(gn);

        print();

    }

    return 0;

}



/**

11 16

1 2

2 3

2 5

3 4

4 3

4 7

5 2

5 4

5 6

6 7

6 10

7 8

8 9

9 10

10 11

11 6

***/


你可能感兴趣的:(LR)