图论(七)--单源最短路

基于算法导论图算法-单源最短路(第24章)

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

题目描述

分别使用Dijkstra和Bellman-Ford算法实现最短路,输出最短路权值和路径

问题分析

这里写图片描述

这里写图片描述

源代码

void Dijkstra(Graph G, Vertex s);//不能用于负圈图
bool bellman_ford(Graph G, Vertex s);//可用于判断负圈
void print_shortest(Graph G, int s);//打印最短路
void print_shortest(Graph G, int s) {
    printf("打印从顶点%d出发到所有顶点的最短路径(含权值):\n",s);
    for (int i = 0; i < G->vexnum; i++) {
        printf(" - %d : 权值(%d),路径为:", i,G->vertices[i].dist);
        print_path_twoPoint(G, s, i);//打印两点路径
        printf("\n");
    }
}

void init_singleSource(Graph G, Vertex s) {
    for (int i = 0; i < G->vexnum; i++) {
        G->vertices[i].dist = INF;
        G->vertices[i].pred = -1;
        G->vertices[i].color = 0;//白色
    }
    G->vertices[s].dist = 0;
}

struct qnode {
    int v;
    int w;
    qnode(int _v = -1,int _w = -1):v(_v),w(_w){}
    bool operator<(const qnode& x)const {
        return w > x.w;//这样优先队列建立小根堆
    }
};

void Dijkstra(Graph G, Vertex s) {//不能用于负圈图
    init_singleSource(G, s);
    priority_queue<qnode> Q;
    Q.push(qnode(s, 0));
    qnode temp;
    PtrToNode ptr;
    while (!Q.empty()) {
        temp = Q.top();
        Q.pop();
        int u = temp.v;

        //下面两行是为了避免已经求出的最短路的顶点再次进行计算
        if (G->vertices[u].color) continue;
        G->vertices[u].color = 1;//黑色

        for (ptr = G->vertices[u].adjto; ptr!=NULL; ptr = ptr->next) {
            //relax松弛操作
            if (!G->vertices[ptr->adjvex].color&&G->vertices[ptr->adjvex].dist > G->vertices[u].dist + ptr->weight) {
                G->vertices[ptr->adjvex].dist = G->vertices[u].dist + ptr->weight;
                G->vertices[ptr->adjvex].pred = u;
                Q.push(qnode(ptr->adjvex, G->vertices[ptr->adjvex].dist));
            }
        }
    }
}



bool bellman_ford(Graph G, Vertex s) {//可用于判断负圈
    PtrToNode ptr;
    init_singleSource(G, s);

    for (int i = 0; i < G->vexnum - 1; i++) {//对所有边松弛n-1次,如果还可以松弛,证明图有负环

        for (int j = 0; j < G->vexnum; j++) {
            for (ptr = G->vertices[j].adjto; ptr != NULL; ptr = ptr->next) {
                //松弛操作
                if (G->vertices[ptr->adjvex].dist > G->vertices[j].dist + ptr->weight) {
                    G->vertices[ptr->adjvex].dist = G->vertices[j].dist + ptr->weight;
                    G->vertices[ptr->adjvex].pred = j;
                }
            }
        }
    }

    for (int j = 0; j < G->vexnum; j++) {//检测看是否图有负环
        for (ptr = G->vertices[j].adjto; ptr != NULL; ptr = ptr->next) {
            if (G->vertices[ptr->adjvex].dist > G->vertices[j].dist + ptr->weight) {
                return false;
            }
        }
    }
    return true;
}


int main() {
    //有向图的随机生成([图论(一)图的建立](http://blog.csdn.net/deep_kang/article/details/70877468))
    CreateRandomDirectGraph();
    Graph G = CreateDirectGraph();

    printf("打印图结构:\n");
    print_EdgeWeight(G);

    /*printf("\n下面是bfs:\n");
    BFS(G, 0);*/
    /*printf("\n下面是dfs:\n");
    DFS(G);*/

    //测试单源最短路
    cout << "测试单源最短路" << endl;
    if (bellman_ford(G, 0)) {
        print_shortest(G, 0);
        Dijkstra(G, 0);
        print_shortest(G, 0);
    }
    else {
        printf("图有负环\n");
    }

    return 0;
}

结果截图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/deep_kang/article/details/71699498