#include<stdio.h>
const int maxnum = 20;
const int maxint = 999999;
// 各数组都从下标1开始(此时图的顶点就是1,2,3....,n)
int dist[maxnum]; // 表示当前点到源点的最短路径长度
int prev[maxnum]; // 记录当前点的前一个顶点(前驱)
int c[maxnum][maxnum]; // 记录图的两点间路径长度
int n, line; // 图的结点数和路径数
//输出v到u的最短路径
void searchPath(int *prev,int v, int u)
{
int que[maxnum]; //利用一位数组实现栈的功能
int tot = 1;
que[tot] = u;
tot++;
int tmp = prev[u];
while(tmp != v&&tmp!=0)
{
que[tot] = tmp;
tot++;
tmp = prev[tmp];
}
que[tot] = v;
printf("当前%d到%d的最短路径: ",v,u);
for(int i=tot; i>=1; --i)
{
printf("%d ",que[i]);
}
printf(" |");
if(dist[u]<maxint)
{
printf("长度为:%d\n",dist[u]);
}
else
{
printf("不存在\n");
}
}
void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
{
bool s[maxnum]; // 判断是否已存入该点到S集合中
for(int k=1; k<=n; ++k)
{
dist[k] = c[v][k];
s[k] = 0; // 初始都未用过该点
if(dist[k] == maxint)
prev[k] = 0; //0表示没有前驱结点
else
prev[k] = v;
}
dist[v] = 0;
s[v] = 1;
// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
for(int i=2; i<=n; ++i)
{
int tmp = maxint;
int u = v;
// 找出当前未使用的点(V-S中的点)j的dist[j]最小值
for(int j=1; j<=n; ++j)
if((!s[j]) && dist[j]<tmp)
{
u = j; // u保存当前邻接点中距离最小的点的号码
tmp = dist[j];
}
s[u] = 1; // 表示u点已存入S集合中
// 更新dist
for(int k=1; k<=n; ++k)
if((!s[k]) && c[u][k]<maxint)
{
int newdist = dist[u] + c[u][k];
if(newdist < dist[k])
{
dist[k] = newdist;
prev[k] = u;
}
}
}
}
void main()
{
int i,j,v;
int begin,end,w;
printf("请输入图的顶点数和路径数\n");
scanf("%d %d",&n,&line);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
c[i][j]=maxint;
printf("请输入各条路径上的权值如顶点1到顶点2的权值为3eg:1,2,3\n");
for(i=1;i<=line;i++)
{
scanf("%d,%d,%d",&begin,&end,&w);
c[begin][end]=w;
}
printf("请输入始点v:\n");
scanf("%d",&v);
Dijkstra(n,v,dist,prev,c);
//输出当前最短路径
for(i=1;i<=n;i++)
if(i!=v)
{
searchPath(prev,v,i);
}
}