文字描述

  求每一对顶点间的最短路径,可以每次以一个顶点为源点,重复执行迪杰斯特拉算法n次。这样,便可求得每一对顶点之间的最短路径。总的执行时间为n^3。但是还有另外一种求每一对顶点间最短路径的方法,就是弗洛伊德(Floyd)算法,它的时间复杂度也为n^3,但是形式上更简单,其基本思想如下:

  

  如果无法理解上面的文字的话,建议看下代码实现部分,可以更容易理解。

示意图

 

算法分析

时间复杂度为n^3

代码实现

 //
// Created by lady on 19-1-6.
// #include <stdlib.h>
#include <stdio.h>
#include <string.h> #define INFINITY 100000 //最大值
#define MAX_VERTEX_NUM 20 //最大顶点数 typedef enum {DG, DN, UDG, UDN} GraphKind; //{有向图,有向网,无向图,无向网}
typedef struct ArcCell{
int weight; //该弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM], PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct VertexType{
char data[];
}VertexType;
typedef struct{
VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
AdjMatrix arcs; //邻接矩阵
int vexnum, arcnum; //图的当前顶点数和弧数
GraphKind kind; //图的种类标志
}MGraph; /*
* 根据顶点信息, 返回该顶点在图中的位置, 如果返回-1表示顶点不存在
*/
static int LocateVex(MGraph *G, char data[])
{
int i = ;
for(i=; i<G->vexnum; i++){
if(!strncmp(G->vexs[i].data, data, strlen(G->vexs[i].data))){
return i;
}
}
return -;
} /*
* 用邻接矩阵作为存储结构,创建有向网
*/
static int CreateGraphDN(MGraph *G)
{
printf("用邻接矩阵创建有向网,输入顶点数,弧数:");
G->kind = DN;
scanf("%d,%d", &G->vexnum, &G->arcnum);
if(G->vexnum > MAX_VERTEX_NUM){
printf("错误:顶点数不能超过%d!!\n", MAX_VERTEX_NUM);
return -;
}
int i = , j = , k = ;
char v1[] = {}, v2[]={}, info[] = {};
char tmp[] = {};
for(i=; i<G->vexnum; i++){
printf("输入第%d个顶点: ", i);
memset(G->vexs[i].data, , sizeof(G->vexs[].data));
scanf("%s", G->vexs[i].data);
for(j=; j<G->vexnum; j++){
G->arcs[i][j].weight = INFINITY;
}
G->arcs[i][i].weight = ;
}
for(k=; k<G->arcnum; k++){
printf("输入第%d条弧(顶点1, 顶点2, 权值): ", k);
memset(tmp, , sizeof(tmp));
scanf("%s", tmp);
sscanf(tmp, "%[^','],%[^','],%s[^\\n]", v1, v2, info);
i = LocateVex(G, v1);
j = LocateVex(G, v2);
if(i< || j< || (!atoi(info))){
printf("错误:顶点%s或者%s不存在, 或者权值信息%s不对!\n", v1, v2, info);
return -;
}
G->arcs[i][j].weight = atoi(info);
}
return ;
} static void printMatrix(int vexnum, VertexType vexs[], int (*arcs)[MAX_VERTEX_NUM])
{
int i = , j = ;
printf("\t");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
}
printf("\n");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
for(j=; j<vexnum; j++){
if(arcs[i][j] == INFINITY){
printf("INF\t");
}else{
printf("%d\t", arcs[i][j]);
}
}
printf("\n");
}
return ;
}
static void printArchs(int vexnum, VertexType vexs[], AdjMatrix arcs)
{
int i = , j = ;
printf("\t");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
}
printf("\n");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
for(j=; j<vexnum; j++){
if(arcs[i][j].weight == INFINITY){
printf("INF\t");
}else{
printf("%d\t", arcs[i][j].weight);
}
}
printf("\n");
}
return ;
} /*
* 用Floyd算法求有向图G中各顶点v和w之间的最短路径P[v][w]及其
* 带权长度D[v][w]。若P[v][w][u]为1, 则u为从v到w当前求得最短路径上的顶点。
*/
void ShortestPath_Floyd(MGraph *G)
{
int u=, v=, w=;
int i=, j=;
int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int D[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//各对结点之间初始已知路径和距离
for(v=; v<G->vexnum; v++){
for(w=; w<G->vexnum; w++){
D[v][w] = G->arcs[v][w].weight;
for(u=; u<G->vexnum; u++){
P[v][w][u] = ;
}
//从v到w有直接路径
if(D[v][w] < INFINITY){
P[v][w][v] = ;
P[v][w][w] = ;
}
}
} for(u=; u<G->vexnum; u++){
for(v=; v<G->vexnum; v++){
for(w=; w<G->vexnum; w++){
if( D[v][u]+D[u][w] < D[v][w]){
//从v经u到w的一条路径更短。
D[v][w] = D[v][u] + D[u][w];
for(i=; i<G->vexnum; i++){
P[v][w][i] = (P[v][u][i] || P[u][w][i]) ? : ;
}
}
}
}
} printf("\n打印各个顶点间的最短路径的权值:\n");
printMatrix(G->vexnum, G->vexs, D); printf("\n打印各个顶点间的最短路径的中间结点:\n");
for(u=; u<G->vexnum; u++){
for(v=; v<G->vexnum; v++){
printf("minpath(%d,%s<->%d,%s):", u, G->vexs[u].data, v, G->vexs[v].data);
for(w=; w<G->vexnum; w++){
if(P[u][v][w] && (u!=v)){
printf("%s\t", G->vexs[w].data);
}
}
printf("\n");
}
} return ;
} int main(int argc, int *argv[])
{
//以邻接矩阵为存储结构创建有向网
MGraph G;
if(CreateGraphDN(&G) < ){
return -;
}
printf("\n打印该图中的信息:\n");
printArchs(G.vexnum, G.vexs, G.arcs);
//Floyd弗洛依德算法求多源最短路径
ShortestPath_Floyd(&G);
}

弗洛依德算法(Floyd)求多源最短路径

代码运行

/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
用邻接矩阵创建有向网,输入顶点数,弧数:,
输入第0个顶点: A
输入第1个顶点: B
输入第2个顶点: C
输入第0条弧(顶点1, 顶点2, 权值): A,B,
输入第1条弧(顶点1, 顶点2, 权值): B,A,
输入第2条弧(顶点1, 顶点2, 权值): A,C,
输入第3条弧(顶点1, 顶点2, 权值): C,A,
输入第4条弧(顶点1, 顶点2, 权值): B,C, 打印该图中的信息:
A B C
A
B
C INF 打印各个顶点间的最短路径的权值:
A B C
A
B
C 打印各个顶点间的最短路径的中间结点:
minpath(,A<->,A):
minpath(,A<->,B):A B
minpath(,A<->,C):A B C
minpath(,B<->,A):A B C
minpath(,B<->,B):
minpath(,B<->,C):B C
minpath(,C<->,A):A C
minpath(,C<->,B):A B C
minpath(,C<->,C): Process finished with exit code

图->最短路径->多源最短路径(弗洛伊德算法Floyd)的更多相关文章

  1. 图->最短路径->单源最短路径(迪杰斯特拉算法Dijkstra)

    文字描述 引言:如下图一个交通系统,从A城到B城,有些旅客可能关心途中中转次数最少的路线,有些旅客更关心的是节省交通费用,而对于司机,里程和速度则是更感兴趣的信息.上面这些问题,都可以转化为求图中,两 ...

  2. 最短路径问题---Floyed(弗洛伊德算法),dijkstra算法,SPFA算法

    在NOIP比赛中,如果出图论题最短路径应该是个常考点. 求解最短路径常用的算法有:Floyed算法(O(n^3)的暴力算法,在比赛中大概能过三十分) dijkstra算法 (堆优化之后是O(MlogE ...

  3. dijkstra 两点的最短路径 单源 最短路径

    思路以dist数组 来扩充  路径的访问,不断的刷新dist数组 设置一个顶点的集合s,并不断地扩充这个集合,一个顶点属于集合s当且仅当从源点到该点的路径已求出.开始时s中仅有源点,并且调整非s中点的 ...

  4. 单源最短路径Dijkstra算法,多源最短路径Floyd算法

    1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...

  5. Dijkstra算法——单源最短路径问题

    学习一个点到其余各个顶点的最短路径--单源最短路径 Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向 ...

  6. 弗洛伊德算法(Floyd算法)

    原博来自http://www.cnblogs.com/skywang12345/ 弗洛伊德算法介绍 和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的 ...

  7. SPFA解决单源最短路径

    SPFA(Shortest Path Faster Algorithm): 一:基本算法 在求解单源最短路径的时候,最经典的是 Dijkstra 算法,但是这个算法对于含有负权的图就无能为力了,而 B ...

  8. 经典问题----最短路径(Floyd弗洛伊德算法)(HDU2066)

    问题简介: 给定T条路,S个起点,D个终点,求最短的起点到终点的距离. 思路简介: 弗洛伊德算法即先以a作为中转点,再以a.b作为中转点,直到所有的点都做过中转点,求得所有点到其他点的最短路径,Flo ...

  9. 多源最短路径算法—Floyd算法

    前言 在图论中,在寻路最短路径中除了Dijkstra算法以外,还有Floyd算法也是非常经典,然而两种算法还是有区别的,Floyd主要计算多源最短路径. 在单源正权值最短路径,我们会用Dijkstra ...

随机推荐

  1. python数据分析实用小抄

    1. python数据分析基础 2. numpy 3. Scikit-Learn 4. Bokeh 5. Scipy 6. Pandas   转载于:http://www.jianshu.com/p/ ...

  2. exp导出数据时丢表

    友军发来消息,说使用exp导出某个schema的数据的时候,发现有些表没有导出来.因为一直没有使用exp的习惯,就使用exp\expdp再次导出一次,分析二者的日志,发现exp的确有些表没有导出. 问 ...

  3. Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 2)

    在我们设计和开发应用程序时,经常要用到控件.比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件.属性可以更改它的外观,比如背景色,标题等, ...

  4. 抽奖 mark

    https://blog.csdn.net/Oversdownload/article/details/77454006?utm_source=blogxgwz5

  5. 告别set和get,两大利器轻松搞定model转换

    场景一:一般我们遇到需要新建model,常规做法就是创建一个类,老老实实的定义好model中的所有属性,一般来说属性对应的set方法和get方法都是少不了的,有时候还需要toString甚至equal ...

  6. [Linux]linux下取消用户名和密码直接登录

    假定目前只有root用户,则有如下两种方式可直接登录系统: 方式一: 1. passwd -d root 2. 修改/lib/systemd/system/serial-getty\@.service ...

  7. 使用winsw部署spring boot jar 项目

    参考:用winsw让任何Windows程序都能运行为服务 简介在linux下部署springboot项目是一件很简单的事,直接后台运行就行了,最多写个shell脚本开机自启就行了.我们最近做的项目需要 ...

  8. Linux 文件普通权限_011

    一.文件权限10个字符对应类型和权限 二.Linux普通文件和Linux目录读.写.执行权限说明 标注:Linux 中的文件名是存在于父目录的block里面,并指向这个文件的inode节点 1.lin ...

  9. Linux date 命令

    date命令用于打印或设置系统日期和时间,常见用法如下: [root@localhost ~]# date //查看当前时间 [root@localhost ~]# date +"%Y-%m ...

  10. Ubuntu 安装mono

    Ubuntu 安装mono 我的系统:Ubuntu 16   Mono参考: http://www.mono-project.com/docs/getting-started/install/linu ...