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

Сайт: Информатикс
Курс: Алгоритмы на графах
Книга: Реализация поиска сильно связных компонент в графе
Напечатано:: Гость
Дата: Среда, 3 Сентябрь 2025, 17:25

Оглавление

//(C) Igor Kvasov
const
  maxn = 100;
var
  ne,ne_T,was,list,ans:array[1..maxn]of longint;
  e,e_T:array[1..maxn,1..maxn]of longint;
  i,j,n,m,u,v,nlist,color:longint;

procedure find(i:longint);
var
  j:longint;
begin
  was[i]:=1;
  for j:=1 to ne[i] do if was[e[i,j]]=0 then find(e[i,j]);
  inc(nlist); list[nlist]:=i;
end;

procedure find_T(i:longint);
var
  j:longint;
begin
  was[i]:=1;
  for j:=1 to ne_T[i] do if was[e_T[i,j]]=0 then find_T(e_T[i,j]);
  ans[i]:=color;
end;

begin
  read(n,m);
  for i:=1 to m do begin
    read(u,v);
    inc(ne[u]); e[u,ne[u]]:=v;
    inc(ne_T[v]); e_T[v,ne_T[v]]:=u;
  end;
  for i:=1 to n do if was[i]=0 then find(i);
  fillchar(was,sizeof(was),0);
  for i:=n downto 1 do if was[list[i]]=0 then begin
    inc(color);
    find_T(list[i]);
  end;
  writeln(color);
  for i:=1 to color do begin
    for j:=1 to n do if ans[j]=i then write(j,' ');
    writeln;
  end;
end.

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;
}