图论(五)--强连通分量

来源:互联网 发布:手机数据魔方 编辑:程序博客网 时间:2024/06/05 07:26

基于算法导论图算法-强连通分量

  • 题目描述
  • 问题分析
  • 源代码
  • 结果截图

题目描述

求图的连通分量

问题分析

先对原图进行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;}

结果截图

这里写图片描述

0 0
原创粉丝点击