图->最短路径->多源最短路径(弗洛伊德算法Floyd)
文字描述
求每一对顶点间的最短路径,可以每次以一个顶点为源点,重复执行迪杰斯特拉算法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)的更多相关文章
- 图->最短路径->单源最短路径(迪杰斯特拉算法Dijkstra)
文字描述 引言:如下图一个交通系统,从A城到B城,有些旅客可能关心途中中转次数最少的路线,有些旅客更关心的是节省交通费用,而对于司机,里程和速度则是更感兴趣的信息.上面这些问题,都可以转化为求图中,两 ...
- 最短路径问题---Floyed(弗洛伊德算法),dijkstra算法,SPFA算法
在NOIP比赛中,如果出图论题最短路径应该是个常考点. 求解最短路径常用的算法有:Floyed算法(O(n^3)的暴力算法,在比赛中大概能过三十分) dijkstra算法 (堆优化之后是O(MlogE ...
- dijkstra 两点的最短路径 单源 最短路径
思路以dist数组 来扩充 路径的访问,不断的刷新dist数组 设置一个顶点的集合s,并不断地扩充这个集合,一个顶点属于集合s当且仅当从源点到该点的路径已求出.开始时s中仅有源点,并且调整非s中点的 ...
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- Dijkstra算法——单源最短路径问题
学习一个点到其余各个顶点的最短路径--单源最短路径 Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向 ...
- 弗洛伊德算法(Floyd算法)
原博来自http://www.cnblogs.com/skywang12345/ 弗洛伊德算法介绍 和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的 ...
- SPFA解决单源最短路径
SPFA(Shortest Path Faster Algorithm): 一:基本算法 在求解单源最短路径的时候,最经典的是 Dijkstra 算法,但是这个算法对于含有负权的图就无能为力了,而 B ...
- 经典问题----最短路径(Floyd弗洛伊德算法)(HDU2066)
问题简介: 给定T条路,S个起点,D个终点,求最短的起点到终点的距离. 思路简介: 弗洛伊德算法即先以a作为中转点,再以a.b作为中转点,直到所有的点都做过中转点,求得所有点到其他点的最短路径,Flo ...
- 多源最短路径算法—Floyd算法
前言 在图论中,在寻路最短路径中除了Dijkstra算法以外,还有Floyd算法也是非常经典,然而两种算法还是有区别的,Floyd主要计算多源最短路径. 在单源正权值最短路径,我们会用Dijkstra ...
随机推荐
- mysql distinct 用法详解及优化
本事例实验用表task,结构如下 MySQL> desc task; +-------------+------------+------+-----+-------------------+- ...
- 这些APP开发技巧可少花60万!
用户需求——我偏不用干嘛要装? 随着手机的普及,大众流量的端口从电脑转移到手机,传统的商业平台从线下到电脑再到手机进行了转换.手机APP作为移动互联网的入口,众多创业者凭借一个手机APP成就了亿万财富 ...
- 摘:PC客户端 XP兼容性调查
现象1:XP SP2下,客户端安装失败(或者启动失败) 解决方案:需要安装以下3个补丁(已经集成到安装包中) ==系统Hotfix(仅仅XP SP2需要安装): http://support.micr ...
- Effective Java 第三版——65. 接口优于反射
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- Redis面试刁难大全
转自:https://mp.weixin.qq.com/s?__biz=MzI0MzQyMTYzOQ==&mid=2247483686&idx=1&sn=18dfa0fd08b ...
- is not in the sudoers file解决方法
用sudo时提示"xxx is not in the sudoers file. This incident will be reported.其中XXX是你的用户名,也就是你的用户名没有权 ...
- 如何建立nfs网络文件系统
建立网络文件系统的前提:windows与linux虚拟机及开发板三者之间能够互相ping 通. 三者互ping通IP设置举例: 1. 首先,关闭windows的防火墙,然后通过:ufw disab ...
- RxAndroid防止内存泄露
RxJava并不会自动防止这种情况发生,好在它可以很容易地防止内存泄露.Observable.subscribe()方法会返回一个Subscription对象,这个对象仅仅有两个方法:isSbscri ...
- Golang 笔记 1 基础、基本数据类型
一.Go语言基础 1. 基础 Go语言中的标识符必须以字母(Unicode字母,PHP/JS可以用中文作为变量名)下划线开头.大写字母跟小写字母是不同的:Hello和hello是两个不同的名字. G ...
- php冒泡排序详解笔记
冒泡 /* * 冒泡排序(从小到大) * 介绍: * 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来. * 思路: * 比较相邻的元素.如果第一个比第二个大,就交换他 ...