基于算法导论图算法-强连通分量
- 题目描述
- 问题分析
- 源代码
- 结果截图
题目描述
求图的连通分量
问题分析
先对原图进行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.youkuaiyun.com/deep_kang/article/details/70877468),这里以十个顶点做测试
printf("打印图结构:\n");
print_graph(G);//打印图
printf("\n求强连通分量:\n");
strongly_connected_components(G);
return 0;
}
结果截图