• Floyd算法解决多源最短路径问题


    Floyd-Warshall算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包。

    Floyd-Warshall算法的时间复杂度为O(N^3),空间复杂度为O(N^2)。

    Floyd-Warshall算法的原理是动态规划:

    从i到j,要么是直接从i到j的,要么是从i出发经过中间节点到j的,假设中间节点有k种可能,那么只要求出这k种可能的最小值,即可得到最短路径。

    d[ i ][ j ]=min{ d[ i ][ k ]+d[ k ][ j ],d[ i ][ k ] } (k from 0 to n)

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define max 100
    #define INF 999
    int graph[max][max];
    int vertex_num;
    int edge_num;
    int d[max][max];
    int p[max][max];
    
    void Floyd(){
        int i,j,k;
        for(i=0;i<vertex_num;i++){
            for(j=0;j<vertex_num;j++){
                d[i][j]=graph[i][j];
                p[i][j]=-1;
            }
        }
        for(k=0;k<vertex_num;k++){
            for(i=0;i<vertex_num;i++){
                for(j=0;j<vertex_num;j++){
                    if(d[i][j]>d[i][k]+d[k][j]){
                        d[i][j]=d[i][k]+d[k][j];
                        p[i][j]=k;
                    }
                }
            }
        }    
        
    }
    void find_path(int i,int j){
        int k;
        k=p[i][j];
        if(k==-1)return;
        find_path(i,k);
        printf("%d ",k);
        find_path(k,j);
    }
    void show_path(){
        int i,j;
        
        printf("Output:
    ");
        for(i=0;i<vertex_num;i++){
            for(j=0;j<vertex_num;j++){
                if(d[i][j]==INF){
                    if(i!=j)printf("No path from %d to %d
    ",i,j);
                }else{
                    printf("Path from %d to %d: ",i,j);
                    printf("%d ",i);
                    find_path(i,j);
                    printf(" %d",j);
                    printf(" distance:%-5d
    ",d[i][j]);
                }
            }
            printf("
    ");
        }
    }
    
    int main(){
        int i,j;
        FILE *fin  = fopen ("dij.in", "r");
        FILE *fout = fopen ("dij.out", "w");
        
        char buf[10];
        fgets(buf,10,fin);
        edge_num=atoi(buf);
        
        printf("edge_num:%d
    ",edge_num);
        fgets(buf,10,fin);
        vertex_num=atoi(buf);
    
        printf("vertex_num:%d
    ",vertex_num);
        
        for(i=0;i<edge_num;i++){
            int start,end,weight;//start point,end point and the weight of edge
            fgets(buf,10,fin);
            sscanf(buf,"%d %d %d",&start,&end,&weight);
            
            printf("start:%d end:%d weight:%d
    ",start,end,weight);
            graph[start][end]=weight;//init the graph matrix 
            
        }
    
        Floyd();
        show_path();
        return 0;
    } 

    测资:

    7
    5
    0 1 100
    0 2 30
    0 4 10
    2 1 60
    2 3 60
    3 1 10
    4 3 50

     结果:

    Output:
    Path from 0 to 1: 0 4 3 1 distance:70
    Path from 0 to 2: 0 2 distance:30
    Path from 0 to 3: 0 4 3 distance:60
    Path from 0 to 4: 0 4 distance:10

    No path from 1 to 0
    No path from 1 to 2
    No path from 1 to 3
    No path from 1 to 4

    No path from 2 to 0
    Path from 2 to 1: 2 1 distance:60
    Path from 2 to 3: 2 3 distance:60
    No path from 2 to 4

    No path from 3 to 0
    Path from 3 to 1: 3 1 distance:10
    No path from 3 to 2
    No path from 3 to 4

    No path from 4 to 0
    Path from 4 to 1: 4 3 1 distance:60
    No path from 4 to 2
    Path from 4 to 3: 4 3 distance:50

  • 相关阅读:
    Centos 通过yum的方式升级内核
    docker入门——镜像简介
    docker入门——管理容器
    docker入门——安装及简单操作
    docker入门——简介
    Centos 6安装 Jenkins
    Centos 7 搭建OpenStack 私有云——(1)基础环境配置
    Python正则表达式
    多选控件multipicker
    绝对定位 软键盘弹出时顶起底部按钮
  • 原文地址:https://www.cnblogs.com/houshengtao/p/6146920.html
Copyright © 2020-2023  润新知