1. Introducción a componentes fuertemente conectados:
en un gráfico dirigido G, si vi,vj
hay una ruta dirigida de vi a vj entre dos vértices , y también hay una ruta dirigida de vj a vi, se llamaDos vértices están fuertemente conectados. Si cada dos vértices del grafo dirigido G están fuertemente conectados, se dice que G es unGráfico fuertemente conectado。Los subgrafos fuertemente conectados de un grafo dirigido se denominan componentes fuertemente conectados。
Método para resolver los componentes fuertemente conectados de la siguiente manera:
2, algoritmo de Kosaraju:
Algoritmo Basado en el hecho de que: una figura inversa G^T
(con direcciones opuestas en cada lado del dibujo) y la imagen G
conectan componentes con idénticos Es decir, si el vértice. s
Y t
en G
el Da es mutuo, si y solo si s
y t
en G^T
el son de la cruz.
2.1. Pasos del algoritmo y diagrama esquemático:
paso 1: primer recorrido en profundidad de la imagen original G,Registre la hora de salida de cada nodo.
Paso 2: Seleccione el vértice con la última hora de salida, G^T
recorra el gráfico inverso y elimine los vértices que se pueden atravesar Estos vértices constituyen un fuerte componente conectado.
paso 3: Si hay vértices que no se han eliminado, continúe con el paso 2; de lo contrario, el algoritmo finaliza.
Figura 1: Gráfico original G
Figura 2: Gráfico G con dfs
Figura 3: Gráfico inverso G ^ T
Figura 4: Gráfico inverso dfs, para obtener componentes conectados fuertes == (El gráfico inverso toma el último nodo de salida como el punto de partida para DFS, atravesado al Los nodos constituyen un componente fuertemente conectado) ==
2.2. Código C ++:
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=110;
int n; // 节点个数
bool flag[MAXN];//访问标志数组
int belg[MAXN];//存储强连通分量,其中belg[i]表示顶点i属于第belg[i]个强连通分量
int numb[MAXN];//结束时间标记,其中numb[i]表示离开时间为i的顶点
int G[MAXN][MAXN],GT[MAXN][MAXN]; //邻接矩阵,逆邻接矩阵
AdjTableadj[MAXN],radj[MAXN];//邻接表,逆邻接表
//用于第一次深搜,求得numb[1..n]的值
voidVisitOne(int cur,int &sig) // 访问原图
{
flag[cur]=true;
for(int i=0; i<n; ++i)
if(G[cur][i] && flag[i] == false)
VisitOne(i,sig);
numb[++sig]=cur; //其中numb[i]表示离开时间为i的顶点
}
//用于第二次深搜,求得belg[1..n]的值
voidVisitTwo(int cur,int count) //访问逆图
{
flag[cur]=true;
belg[cur]=count;
for(int i=0; i<n; ++i)
if(GT[cur][i] && flag[i] == false)
VisitOne(i,count);
}
//Kosaraju算法,返回为强连通分量个数
int Kosaraju_StronglyConnectedComponent()
{
int sig=0;// sig代表离开时间
//第一次深搜
memset(flag,0,sizeof(bool)*n); //访问标志设为false
for(int i=0; i<n; i++)
if( flag[i] == false)
VisitOne(i,sig);
//第二次深搜
memset(flag,0,sizeof(bool)*n); //访问标志设为false
int count=0; // count为强连通分量个数
for(int i=n; i>0; --i)
if(flag[numb[i]] == false) //频率最高的顶点若没访问
VisitTwo(numb[i],++count);
return count;
}
Materiales de referencia:
a. Enciclopedia Baidu: algoritmo
b de kosaraju , componente
c conectado fuerte , introducción al algoritmo sección 22.5 componente conectado fuerte
3. Algoritmo de Tarjan y algoritmo de Gabow.
No he aprendido estos dos. Si está interesado, consulte el enlace: Enciclopedia de Baidu: Componentes fuertemente conectados
para resumir:
1. Algoritmo de Kosaraju: el gráfico inverso toma el último nodo de salida como punto de partida para DFS, y los nodos atravesados forman un componente conectado fuerte.