/*
有向网图的最短路径-Floyd算法及路径打印
输出结果:
请输入图的顶点和弧的个数:
7 12
请依次输入图的7个顶点信息:
V0
V1
V2
V3
V4
V5
V6
请依次输入图的弧<Vi, Vj>上下标及对应权值:
0 1 2
0 3 1
1 3 3
1 4 10
2 0 4
2 5 5
3 2 2
3 4 2
3 5 8
3 6 4
4 6 6
6 5 1
图的邻接矩阵为:
V0 V1 V2 V3 V4 V5 V6
V0 0 2 ∞ 1 ∞ ∞ ∞
V1 ∞ 0 ∞ 3 10 ∞ ∞
V2 4 ∞ 0 ∞ ∞ 5 ∞
V3 ∞ ∞ 2 0 2 8 4
V4 ∞ ∞ ∞ ∞ 0 ∞ 6
V5 ∞ ∞ ∞ ∞ ∞ 0 ∞
V6 ∞ ∞ ∞ ∞ ∞ 1 0
最终dist数组为:
0 2 3 1 3 6 5
9 0 5 3 5 8 7
4 6 0 5 7 5 9
6 8 2 0 2 5 4
∞ ∞ ∞ ∞ 0 7 6
∞ ∞ ∞ ∞ ∞ 0 ∞
∞ ∞ ∞ ∞ ∞ 1 0
最终path数组为:
0 1 3 3 3 3 3
3 1 3 3 3 3 3
0 0 2 0 0 5 0
2 2 2 3 4 6 6
0 1 2 3 4 6 6
0 1 2 3 4 5 6
0 1 2 3 4 5 6
各顶点间的最短路径和权值和为:
V0-V0: V0-->V0-->(0)
V0-V1: V0-->V1-->(2)
V0-V2: V0-->V3-->V2-->(3)
V0-V3: V0-->V3-->(1)
V0-V4: V0-->V3-->V4-->(3)
V0-V5: V0-->V3-->V6-->V5-->(6)
V0-V6: V0-->V3-->V6-->(5)
V1-V0: V1-->V3-->V2-->V0-->(9)
V1-V1: V1-->V1-->(0)
V1-V2: V1-->V3-->V2-->(5)
V1-V3: V1-->V3-->(3)
V1-V4: V1-->V3-->V4-->(5)
V1-V5: V1-->V3-->V6-->V5-->(8)
V1-V6: V1-->V3-->V6-->(7)
V2-V0: V2-->V0-->(4)
V2-V1: V2-->V0-->V1-->(6)
V2-V2: V2-->V2-->(0)
V2-V3: V2-->V0-->V3-->(5)
V2-V4: V2-->V0-->V3-->V4-->(7)
V2-V5: V2-->V5-->(5)
V2-V6: V2-->V0-->V3-->V6-->(9)
V3-V0: V3-->V2-->V0-->(6)
V3-V1: V3-->V2-->V0-->V1-->(8)
V3-V2: V3-->V2-->(2)
V3-V3: V3-->V3-->(0)
V3-V4: V3-->V4-->(2)
V3-V5: V3-->V6-->V5-->(5)
V3-V6: V3-->V6-->(4)
V4-V0: V4-->V0-->(∞)
V4-V1: V4-->V1-->(∞)
V4-V2: V4-->V2-->(∞)
V4-V3: V4-->V3-->(∞)
V4-V4: V4-->V4-->(0)
V4-V5: V4-->V6-->V5-->(7)
V4-V6: V4-->V6-->(6)
V5-V0: V5-->V0-->(∞)
V5-V1: V5-->V1-->(∞)
V5-V2: V5-->V2-->(∞)
V5-V3: V5-->V3-->(∞)
V5-V4: V5-->V4-->(∞)
V5-V5: V5-->V5-->(0)
V5-V6: V5-->V6-->(∞)
V6-V0: V6-->V0-->(∞)
V6-V1: V6-->V1-->(∞)
V6-V2: V6-->V2-->(∞)
V6-V3: V6-->V3-->(∞)
V6-V4: V6-->V4-->(∞)
V6-V5: V6-->V5-->(1)
V6-V6: V6-->V6-->(0)
请按任意键继续. . .
*/
# include <stdio.h>
# include <stdlib.h>
# define VEXMAX 100
# define SIZE 5
# define INF 0X3f3f3f3f
typedef char VertexType[SIZE];
typedef int EdgeType;
typedef struct{
VertexType vexs[VEXMAX];
EdgeType arc[VEXMAX][VEXMAX];
int vexNum, edgeNum;
}MGraph;
void CreateMGraph(MGraph * G);//创建图的邻接矩阵
void PrintMGraph(MGraph G);// 打印图的邻接矩阵
void Floyd(MGraph G, int ** path, int ** dist);//最短路径-弗洛伊德算法
void PrintRoad(MGraph G, int ** path, int ** dist);//打印最短路径
int main(void)
{
int start;
MGraph G;
CreateMGraph(&G);
PrintMGraph(G);
//创建二维数组path保存各路径下标,二维数组dist保存各顶点到各顶点的最短路径权值
int ** path = (int **)malloc(G.vexNum * sizeof(int*));
int ** dist = (int **)malloc(G.vexNum * sizeof(int*));
for(int i = 0; i < G.vexNum; i++)
{
*(path + i) = (int*)malloc(G.vexNum * sizeof(int));
*(dist + i) = (int*)malloc(G.vexNum * sizeof(int));
}
Floyd(G, path, dist);
PrintRoad(G, path, dist);
for(int i = 0; i < G.vexNum; i++)
{
free(*(path + i));
free(*(dist + i));
*(path + i) = NULL;
*(dist + i) = NULL;
}
system("pause");
return 0;
}
//创建图的邻接矩阵
void CreateMGraph(MGraph * G)
{
int i, j, k, w;
printf("请输入图的顶点和弧的个数:\n");
scanf("%d %d", &G->vexNum, &G->edgeNum);
printf("请依次输入图的%d个顶点信息:\n", G->vexNum);
for(i = 0; i < G->vexNum; i++)
scanf("%s", &G->vexs[i]);
for(i = 0; i < G->vexNum; i++)
{
for(j = 0; j < G->vexNum; j++)
{
if(i == j)
G->arc[i][j] = 0;
else
G->arc[i][j] = INF;
}
}
printf("请依次输入图的弧<Vi, Vj>上下标及对应权值:\n");
for(k = 0; k < G->edgeNum; k++)
{
scanf("%d %d %d", &i, &j, &w);
G->arc[i][j] = w;
}
}
// 打印图的邻接矩阵
void PrintMGraph(MGraph G)
{
int i, j;
printf("图的邻接矩阵为:\n");
for(i = 0; i < G.vexNum; i++)
printf("\t%s", G.vexs[i]);
printf("\n");
for(i = 0; i < G.vexNum; i++)
{
printf("%s\t", G.vexs[i]);
for(j = 0; j < G.vexNum; j++)
{
if(G.arc[i][j] == INF)
printf("∞\t");
else
printf("%d\t", G.arc[i][j]);
}
printf("\n");
}
}
//最短路径-弗洛伊德算法
void Floyd(MGraph G, int ** path, int ** dist)
{
int i, j, k;
for(i = 0; i < G.vexNum; i++)
{
for(j = 0; j < G.vexNum; j++)
{
dist[i][j] = G.arc[i][j];//初始为两顶点间对应权值
path[i][j] = j;//初始为经过顶点下标
}
}
for(k = 0; k < G.vexNum; k++)
{
for(i = 0; i < G.vexNum; i++)
{
for(j = 0; j < G.vexNum; j++)
{
//若经过新顶点K路径比原路径更短,则更新最短路径并记录经过下标为k的顶点
if(dist[i][j] > dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = path[i][k];
}
}
}
}
}
//打印最短路径
void PrintRoad(MGraph G, int ** path, int ** dist)
{
int i, j, k;
printf("最终dist数组为:\n");
for(i = 0; i < G.vexNum; i++)
{
for(j = 0; j < G.vexNum; j++)
{
if(dist[i][j] != INF)
printf("\t%d", dist[i][j]);
else
printf("\t∞");
}
printf("\n");
}
printf("最终path数组为:\n");
for(i = 0; i < G.vexNum; i++)
{
for(j = 0; j < G.vexNum; j++)
{
printf("\t%d", path[i][j]);
}
printf("\n");
}
printf("各顶点间的最短路径和权值和为:\n");
for(i = 0; i < G.vexNum; i++)
{
for(j = 0; j < G.vexNum; j++)
{
printf("%s-%s:\t", G.vexs[i], G.vexs[j]);
printf("%s-->", G.vexs[i]);
k = path[i][j];//找到下一个顶点
while(k != j)//循环打印路径点直到找到终点
{
printf("%s-->", G.vexs[k]);
k = path[k][j];//找到下一个顶点
}
printf("%s-->", G.vexs[j]);//打印终点
if(dist[i][j] != INF)
printf("(%d)\n", dist[i][j]);
else
printf("(∞)\n");
}
printf("\n");
}
}