有向图如果是强连通的:那么通过dfs,可以从一个顶点开始,访问到每一个节点。
如果有向图不是强连通的,可以在某个未作标记的节点处开始,反复执行深度优先操作,直到所有的节点都被访问到。
通过两次深度优先搜索可以检测一个有向图是否是强连通的,如果它不是强连通的,我们可以得到一些子集,它们到自身是强连通的,称它们为图中的一个强分支。
查找图中强分支的算法:
1.对图进行一次dfs,并对访问的顶点进行编号,然后再把G上的所有边反向,形成Gr
2.对Gr执行dfs,在编号最高的顶点开始新的dfs,一次dfs执行所访问的顶点,即为一个强分支,直到Gr图中没有未被访问的顶点。
代码中使用邻接矩阵存储图
实现代码使用的数据结构
#define MIN -9999 //最小值
Graph G,Gr; //G为初始图,Gr是把G中所有的边,反向形成的图
int visited[MAXVERTEX]; //用来做是否访问标记的
int Num[MAXVERTEX]; //Num数组记录各个顶点的编号
int cut = 1; //编号从1开始
对图顶点进行编号,并把图G中的边反向存储到图Gr中
void DFS(int Vertex)
{
//从Vertex顶点开始进行深度优先搜索
visited[Vertex] = 1; //表示已经访问
for (int w = 0; w < G->Nv; w++)
{
if (G->Graph[Vertex][w] != 0)
{
//将边反向存储到Gr中
Gr->Graph[w][Vertex] = 1;
if(!visited[w]) //若未访问,进行深度优先搜索
DFS(w);
}
}
Num[Vertex] = cut++; //对各个顶点进行编号
}
void ListDFS()
{
for (int i = 0; i < G->Nv; i++)
{
//多次dfs,直到图中所有的顶点都访问到
if (!visited[i])
{
DFS(i);
}
}
}
进行强分支查找
void dfs(int vertex) {
visited[vertex] = 0; //代表已访问该顶点
Num[vertex] = -1; //编号作废
printf("%d ", vertex); //输出顶点
for (int w = 0; w < G->Nv; w++)
{
if (Gr->Graph[vertex][w] != 0 && visited[w])
{
dfs(w); //进行dfs
}
}
}
void StrongBranch() {
int mv, mx;
while (1){
mx = MIN;
for (int i = 0; i < G->Nv;i++) {
//找到编号最大的顶点进行一次DFS
if (Num[i] > mx) {
mx = Num[i];
mv = i;
}
}
if (mx <= 0) //未找到,则图中所有的顶点都已被访问
break;
dfs(mv); //该顶点进行dfs,所访问的所有顶点,都属于一个强分支
printf("\n");
}
}