Реализация поиска сильно связных компонент в графе

Vladimir Sitnikov - 02 Apr 2004

/*
Формат входных данных:
[Число вершин в графе]
[Число ребер, входящих из вершины (вершина номер 0)] [номер вершины, куда ведет связь] [номер вершины, куда ведет связь]
[Число ребер, входящих из вершины (вершина номер 1)] [номер вершины, куда ведет связь] [номер вершины, куда ведет связь]
...
Sample intput:
5
1 1
2 2 3
1 0
1 4
1 3
Sample output:
1 1
2 1
0 1
4 2
3 2
*/
#include <stdio.h>

int N;                // Количество вершин в графе
#define MAX_NODES 100 // Максимальное количество вершин
#define MAX_EDGES 10  // Максимальное количество ребер, выходящих из одной вершины

int edges[MAX_NODES][MAX_EDGES]; // Граф, в котором ищем сильно связные компоненты
int edges_c[MAX_NODES];

int edgesT[MAX_NODES][MAX_EDGES]; // Транспонированый граф
int edgesT_c[MAX_NODES];

int state[MAX_NODES];             // Иcпользуется в поиске для того, чтобы отмечать посещенные вершины

int f[MAX_NODES],last_f=0;        // Список предварительной расстановки вершин

int c=1; // Номер компоненты (увеличиваем его, когда находим новую)

void dfs(int node){
   state[node]=1;

   for(int i=0; i<edges_c[node]; i++) // Самый обыкновенный поиск в глубину.
      if (state[edges[node][i]]==0)
         dfs(edges[node][i]);

   f[last_f++]=node;         
}

void dfsT(int node){
   state[node]=1;

   for(int i=0; i<edgesT_c[node]; i++) // Самый обыкновенный поиск в глубину в транспонированном графе.
      if (state[edgesT[node][i]]==0)   
         dfsT(edgesT[node][i]);         

   printf("%d %d\n",node,c);
}

void scc(){ // Strongly Connected Components - функция выделения сильно связных компонент графа
   int i;
   for(i=0; i<N; i++) state[i]=0;

   for(i=0; i<N; i++)               
      if (state[i]++==0)   
         dfs(i);   

   for(i=0; i<N; i++) state[i]=0;

   for(last_f--; last_f>=0; last_f--)
      if (state[f[last_f]]==0){      
         dfsT(f[last_f]);               
         c++;      
      }
}

int main(){
   int i;

   scanf("%d",&N);
   for(i=0; i<N; i++) edges_c[i]=edgesT_c[i]=0;
   
   for(i=0; i<N; i++){
      int j;
      scanf("%d",&edges_c[i]);
      for(j=0; j<edges_c[i]; j++){
         int to;
         scanf("%d",&to);
         edges[i][j]=to;
         edgesT[to][edgesT_c[to]++]=i;
      }
   }

   scc();

   return 0;
}