由于一维的前驱数组,只能记录一条最短路径,遇到存在多条最短路径便无能为力了。
于是我想了二维的前驱数组。
可以让每个点都维护一个自己的前驱数组,在dijkstra算法松弛操作时,在遇到距离相同的路径时,把这条路径的前驱点记录下来,而不是像一维的前驱数组那样抛弃或者覆盖前驱点,遇到了更短的路径的时候,把相应节点的前驱数组清空,存入新的前驱点。最后通过dfs访问每一条最短路径,求出边数最短的最短路径。
给出代码实现:
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<cstring>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;
int map[10][10];
int dist[10];
int vis[10];
int n, m;
int pre[10][10];
int Count[10];
vector< vector<int> > v(15);
int cnt;
//int ans = 0;
int min(int a, int b)
{
return a < b ? a : b;
}
void dfs(int s, int e, int* Count, int dis, int* ans)
{
vis[s] = 1;
if (s == e && *Count == dis)
{
*(ans) += 1;
return;
}
else
{
for (int i = 1; i <= n; i++)
{
if (map[s][i] && !vis[i])
{
int temp = *Count;
*(Count) += map[s][i];
dfs(i, e, Count, dis, ans);
vis[i] = 0;
*Count = temp;
}
}
}
}
void path(int i)
{
if (i == 0)
{
cnt++;
return;
}
for (int j = 0; j < Count[i]; j++)
{
v[cnt].push_back(i);
path(pre[i][j]);
//printf("%d,", i);
}
}
int main()
{
//ans = 0;
cnt = 0;
memset(Count, 0, sizeof(Count));
memset(pre, 0, sizeof(pre));
puts("请输入图的顶点个数:");
scanf("%d", &n);
puts("请输入图的边的个数:");
scanf("%d", &m);
for (int i = 1; i <= m; i++)
{
puts("输入边:");
int a, b;
int dis;
scanf(" %d %d %d", &a, &b, &dis);
map[a][b] = dis;
}
for (int i = 0; i <= n; i++)
{
dist[i] = inf;
vis[i] = 0;
}
int s;
int e;
char s1;
puts("输入起点编号:");
scanf(" %d", &s);
Count[s]++;
// s = s1 - 'A' + 1;
puts("输入终点编号:");
scanf("%d", &e);
dist[s] = 0;
vis[s] = 1;
for (int i = 1; i <= n; i++)
{
if (map[s][i] != 0)
{
dist[i] = min(dist[i], map[s][i]);
pre[i][Count[i]++] = s;
}
}
for (int i = 1; i <= n - 1; i++)
{
int minn = inf;
int best;
for (int j = 1; j <= n; j++)
{
if (!vis[j] && dist[j] < minn)
{
minn = dist[j];
best = j;
}
}
vis[best] = 1;
for (int j = 1; j <= n; j++)
{
if (map[best][j])
{
if (dist[j] == dist[best] + map[best][j])
{
pre[j][Count[j]++] = best;
}
if (dist[j] > dist[best] + map[best][j])
{
dist[j] = dist[best] + map[best][j];
for (int k = 0; k < Count[j]; k++)
{
pre[j][k] = 0;
}
Count[j] = 0;
pre[j][Count[j]++] = best;
}
}
}
}
/*for (int i = 1; i <= n; i++)
{
vis[i] = 0;
}
int* Count = new(int);
*Count = 0;
int* ans = new(int);
*ans = 0;
dfs(s, e, Count, dist[e], ans);
puts("从起点到终点的最短路径数为:");*/
//printf("%d\n", *ans);
for (int i = 0; i < Count[e]; i++)
{
int temp = pre[e][i];
path(pre[e][i]);
}
int index = 0;
int minn = v[0].size();
puts("各最短路径为:");
for (int i = 0; i < cnt; i++)
{
for (int j = (v[i].size() - 1); j >= 0; j--)
{
printf("%d,", v[i][j]);
}
printf("%d\n", e);
if (minn > v[i].size())
{
minn = v[i].size();
index = i;
}
}
puts("其中边数最小的最短路径是:");
for (int i = v[index].size() - 1; i >= 0; i--)
{
printf("%d,", v[index][i]);
}
printf("%d\n", e);
}
运行结果如图所示: