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:\n");
    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\n",i,j);
            }else{
                printf("Path from %d to %d: ",i,j);
                printf("%d ",i);
                find_path(i,j);
                printf(" %d",j);
                printf(" distance:%-5d\n",d[i][j]);
            }
        }
        printf("\n");
    }
}

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\n",edge_num);
    fgets(buf,10,fin);
    vertex_num=atoi(buf);

    printf("vertex_num:%d\n",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\n",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

 

转载于:https://www.cnblogs.com/houshengtao/p/6146920.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值