圖論(五)--強連通分量
阿新 • • 發佈:2019-01-06
基於演算法導論圖演算法-強連通分量
- 題目描述
- 問題分析
- 原始碼
- 結果截圖
題目描述
求圖的連通分量
問題分析
先對原圖進行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;
}
結果截圖