本文已参与「新人创作礼」活动,一起开启掘金创作之路。
解决稠密图较好
- 准备工作
#include <iostream> //Floyd算法解决稠密图时更好
#include <algorithm>
#include <climits>
#include <cstring>
using namespace std;
const int MaxV = 100;
/*定义边*/
typedef struct ENode{
int v1, v2;
int Weight;
} * Edge;
/*定义邻接矩阵存储的图*/
typedef struct GNode{
int Nv, Ne;
int W[MaxV][MaxV]; //权重
//string Data[MaxV];
int Dist;
} * MGraph;
/*图的初始化*/
MGraph CraeteGraph(int Nv)
{
MGraph G = new GNode;
G->Nv = Nv; G->Ne = 0;
memset(G->W, 0x3f, sizeof(G->W)); //初始化为无穷大,同时要保证无穷大 + 无穷大 还是无穷大
for (int i = 0; i < G->Nv; i++)
G->W[i][i] = 0;
return G;
}
void InsertEdge(MGraph G, Edge E)
{
G->W[E->v1][E->v2] = E->Weight;
G->W[E->v2][E->v1] = E->Weight;
}
MGraph BuildGraph()
{
int Nv; cin >> Nv;
MGraph G = CraeteGraph(Nv);
cin >> G->Ne;
Edge E = new ENode;
for (int i = 0; i < G->Ne; i++)
{
cin >> E->v1 >> E->v2 >> E->Weight;
InsertEdge(G, E);
}
delete E;
return G;
}
- 核心算法
//dp问题dp(k)[i][j]表示: 从i到j的最短路径,k == -1时,表示直接i到j的最短路径, k表示计算的步骤
//状态转换方程: dp(k)[i][j] = min{dp(k - 1)[i][j], dp(k - 1)[i][k] + dp(k - 1)[k][j]}
void Folyd(MGraph G, int dp[][MaxV], int path[][MaxV])
{
/*初始化数组*/
for (int i = 0; i < G->Nv; i++)
for (int j = 0; j < G->Nv; j++)
{
dp[i][j] = G->W[i][j];
path[i][j] = -1;
}
/*dp填表过程*/
for (int k = 0; k < G->Nv; k++)
for (int i = 0; i < G->Nv; i++)
for (int j = 0; j < G->Nv; j++)
if(dp[i][j] > dp[i][k] + dp[k][j])
{
dp[i][j] = dp[i][k] + dp[k][j];
path[i][j] = k;
}
}
void Serch_path(MGraph G, const int path[][MaxV], int i, int j)
{
if(path[i][j] == -1)
{
G->Dist += G->W[i][j]; //统计最短路径
cout << "->" << j;
return;
}
Serch_path(G, path, i, path[i][j]);
Serch_path(G, path, path[i][j], j);
}
void Print(MGraph G, const int path[][MaxV], int i, int j)
{
G->Dist = 0;
cout << i;
Serch_path(G, path, i, j);
cout << " Dist=" << G->Dist;
cout << endl;
}
int main()
{
int dp[MaxV][MaxV];
int path[MaxV][MaxV];
cout << "输入有向图:" << endl;
MGraph G = BuildGraph();
Folyd(G, dp, path);
int start, end;
while (1)
{
cout << "输入起点和终点:" << endl;
cin >> start >> end;
if(start == -1 && end == -1)
break;
else if(start >= 0 && start < G->Nv && end >= 0 && end < G->Nv)
Print(G, path, start, end);
else
cout << "数据不合法" << endl;
}
delete G;
system("pause");
return 0;
}
- 运行结果
输入有向图:
10 17
0 1 2
1 2 5
1 3 2
0 3 5
2 4 8
2 5 4
3 5 4
3 6 2
4 5 2
5 6 3
4 7 5
5 7 9
5 8 6
6 8 7
7 8 3
7 9 4
8 9 8
输入起点和终点:
0 9
0->1->3->5->4->7->9 Dist=19
输入起点和终点:
9 0
9->7->4->5->3->1->0 Dist=19
输入起点和终点:
9 4
9->7->4 Dist=9
输入起点和终点:
2 2
2->2 Dist=0
输入起点和终点:
651 231
数据不合法
输入起点和终点:
-1 -1
请按任意键继续. . .