1. 程式人生 > >圖論(五)--強連通分量

圖論(五)--強連通分量

基於演算法導論圖演算法-強連通分量

  • 題目描述
  • 問題分析
  • 原始碼
  • 結果截圖

題目描述

求圖的連通分量

問題分析

先對原圖進行DFS,在根據結束時間的倒序對原圖的轉置進行DFS即可,具體證明可以參考演算法導論第22章22.5節-強連通分量。

虛擬碼及演算法複雜度:
求連通分量

原始碼

Graph G_Transpose(Graph G);//求圖的轉置
void strongly_connected_components(Graph G);//求強連通分量
void DFS_G_T(Graph G);//對圖的轉置按照結束時間遞減順序DFS

int Time;
int finishTime_descreasing[VertexNum + 1
];//在深搜時按結束時間存 int count_finishTime_descreasing = VertexNum;//陣列下標,從後往前存 void DFS_visit_stack(Graph G, Vertex v) {//深搜用棧實現 PtrToNode ptr; stack<int> S; S.push(v); G->vertices[v].dist = 0; G->vertices[v].color = 1;//灰色 G->vertices[v].discover_time = ++Time; printf("%d"
, v); while (!S.empty()) { Vertex u = S.top(); ptr = G->vertices[u].adjto; while (ptr != NULL) { if (G->vertices[ptr->adjvex].color == 0) { S.push(ptr->adjvex); G->vertices[ptr->adjvex].dist = G->vertices[u].dist + 1
;//權為1計算 G->vertices[ptr->adjvex].color = 1;//灰色 Time++; G->vertices[ptr->adjvex].discover_time = Time; G->vertices[ptr->adjvex].pred = u; printf(" %d", ptr->adjvex); break; } ptr = ptr->next; } if (S.top() == u) { G->vertices[u].color = 2;//黑色 Time++; G->vertices[u].finish_time = Time; finishTime_descreasing[--count_finishTime_descreasing] = u; S.pop(); } } printf("\n"); } void DFS(Graph G) { for (int i = 0; i < G->vexnum; i++) { G->vertices[i].color = 0;//白色 G->vertices[i].pred = -1; } Time = 0; for (int i = 0; i < G->vexnum; i++) { if (G->vertices[i].color == 0) { DFS_visit_stack(G, i); } } } Graph G_Transpose(Graph G) {//求圖的轉置 Graph G_T; PtrToNode ptr, node; //建立圖的初始化 G_T = (struct GraphRecord*)malloc(sizeof(struct GraphRecord)); G_T->vexnum = G->vexnum; G_T->vertices = (struct VertexRecord*)malloc(sizeof(struct VertexRecord)*G_T->vexnum); for (int i = 0; i < G_T->vexnum; i++) { G_T->vertices[i].adjto = NULL; G_T->vertices[i].in_degree = 0; G_T->vertices[i].out_degree = 0; } //建立圖 for (int i = 0; i < G->vexnum; i++) { ptr = G->vertices[i].adjto; while (ptr != NULL) { node = (struct Node*)malloc(sizeof(struct Node)); node->adjvex = i; node->next = G_T->vertices[ptr->adjvex].adjto; G_T->vertices[ptr->adjvex].adjto = node; ptr = ptr->next; } } //print_graph(G_T);列印轉置圖 return G_T; } void DFS_G_T(Graph G) { int count = 0; for (int i = 0; i < G->vexnum; i++) { G->vertices[i].color = 0;//白色 G->vertices[i].pred = -1; } Time = 0; for (int i = 0; i < G->vexnum; i++) { if (G->vertices[finishTime_descreasing[i]].color == 0) { printf("第%d個強連通分量:", ++count); //DFS_VISIT(G, i); DFS_visit_stack(G, finishTime_descreasing[i]); //print_dist_dfs(G, finishTime_descreasing[i]); } } printf("共有%d個強連通分量\n", count); //print_path_everyPoint(G); //print_dist_dfs(G, 0); } void strongly_connected_components(Graph G) { printf("深搜G:"); DFS(G); Graph G_T = G_Transpose(G); /*for (int i = 0; i < VertexNum; i++) {//按遞減順序列印結束時間 printf("頂點%d的結束時間為:%d\n", finishTime_descreasing[i], G->vertices[finishTime_descreasing[i]].finish_time); }*/ printf("按照遞減順序dfs原圖的轉置得到強連通分量:\n"); DFS_G_T(G_T); } int main() { CreateRandomDirectGraph(); Graph G = CreateDirectGraph();//參考[圖論(一)-圖的建立](http://blog.csdn.net/deep_kang/article/details/70877468),這裡以十個頂點做測試 printf("列印圖結構:\n"); print_graph(G);//列印圖 printf("\n求強連通分量:\n"); strongly_connected_components(G); return 0; }

結果截圖

這裡寫圖片描述