迪杰斯特拉最短路径(含路径输出)

模版:

输入

输入的第一行包含2个正整数n和s,表示图***有n个顶点,且源点为s。其中n不超过50,s小于n。

以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。当i和j相等的时候,保证对应的整数为0。

输出

只有一行,共有n-1个整数,表示源点至其它每一个顶点的最短路径长度。如果不存在从源点至相应顶点的路径,输出-1。

请注意行尾输出换行。

样例输入

4 1
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0
#include<stdio.h>
#include<string.h>
#define inf 99999999
int map[60][60],book[60],p[60],dis[60];
//p数组用来记录s点到各个点的路径,例如,p[i]的值为结点i的上一步。 
void putlu(int u,int v)
{
	//通过v结点的上一结点查找到u结点,将路径存到栈s中,最后输出。 
	int s[60],k,i,l;
	k=0;
	l=p[v];
	while(l!=u)
	{
		s[k++]=l;
		l=p[l];
	}
	printf("%d",u);
	for(i=k-1;i>=0;i--)
		printf("--->%d",s[i]);
	printf("--->%d\n",v);
}
int main()
{
	int n,s,min,i,j,u,v;
	scanf("%d%d",&n,&s);
	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
		{
			scanf("%d",&map[i][j]);
			if(i!=j&&map[i][j]==0)
				map[i][j]=inf;
		}
	memset(book,0,sizeof(book));
	memset(p,-1,sizeof(book));
	for(i=0;i<n;i++)
	{
		dis[i]=map[s][i];
		if(dis[i]!=inf)//若结点s可以到达结点i则p[i]为s。说明i结点可以通过结点s到达。 
			p[i]=s;
	}
	book[s]=1;
	for(i=0;i<n;i++)
	{
		min=inf;
		for(j=0;j<n;j++)
		{
			if(min>dis[j]&&book[j]==0)
			{
				min=dis[j];
				u=j;
			}
		}
		book[u]=1;
		for(j=0;j<n;j++)
		{
			if(dis[j]>dis[u]+map[u][j])
			{
				dis[j]=dis[u]+map[u][j];
				p[j]=u;  //通过u结点更新j结点的最短路径,说明到达j结点的路径通过u。 
			}
		}
	}
	for(i=0;i<n;i++)
	{
		if(i==s)
			continue;
		if(dis[i]!=inf)
		{
			printf("从%d点到%d点的最短路径为:\n",s,i);
			putlu(s,i);		//输出路径 
			printf("长度为:%d\n\n\n",dis[i]);
		}
		else
		{
			printf("不能从%d点到%d点。\n"); 
		}
	}
	return 0;
}