给定一个有向图,规定源点为0,求源点0到其他顶点最短路径。###你要实现的 函数接口定义:
void Dijkstra(MGraph g,int v);//源点v到其他顶点最短路径
裁判测试程序样例:
#include <stdio.h>
#include <iostream>
#define MaxSize 100
#define INF 32767 //INF表示∞
#define MAXV 100 //最大顶点个数
using namespace std;
/*有向图的邻接矩阵,顶点编号0开始 */
typedef struct //图的定义
{ int **edges; //邻接矩阵
int n,e; //顶点数,弧数
} MGraph; //图的邻接矩阵表示类型
void CreateMGraph(MGraph &g,int n,int e );//n为顶点数,e为边数,g为有向图
void Dispath(int dist[],int path[],int s[],int n,int v);
/*输入最短路径,dist各顶点最短距离,path最短路径前驱,n顶点数,v源点 */
void Dijkstra(MGraph g,int v); //源点v到其他顶点最短路径
void Ppath(int path[],int i,int v); //前向递归查找路径上的顶点
void PrintMGraph(MGraph g); //输出邻接矩阵,释放内存
int main()
{
MGraph g;
int n,e;
cin>>n>>e;
CreateMGraph(g,n,e );
//PrintMGraph(g);
Dijkstra(g,0);
return 0;
}
void CreateMGraph(MGraph &g,int n,int e )
{
int i,j,a,b,weight;
g.edges=new int *[n];
for(i=0;i<n;i++) g.edges[i]=new int[n];
for(i=0;i<n;i++)
for(j=0;j<n;j++)
g.edges[i][j]=INF;
for(i=1;i<=e;i++)
{
cin>>a>>b>>weight;
g.edges[a][b]=weight;
}
g.n=n;
g.e=e;
}
void PrintMGraph(MGraph g)
{
int i,j;
for(i=0;i<g.n;i++)
{
for(j=0;j<g.n;j++) cout<<g.edges[i][j]<<" ";
cout<<endl;
}
for(i=0;i<g.n;i++)
delete[] g.edges[i];
}
void Ppath(int path[],int i,int v) //前向递归查找路径上的顶点
{
int k;
k=path[i];
if (k==v) return; //找到了起点则返回
Ppath(path,k,v); //找顶点k的前一个顶点
printf(" %d",k); //输出顶点k
}
void Dispath(int dist[],int path[],int s[],int n,int v)
{
int i;
for (i=0;i<n;i++)
if (s[i]==1&&i!=v)
{
printf("从%d到%d的最短路径长度为:%d,路径为:",v,i,dist[i]);
printf("%d",v); //输出路径上的起点
Ppath(path,i,v); //输出路径上的中间点
printf(" %d",i); //输出路径上的终点
cout<<endl;
}
else if(s[i]==0)
printf("从%d到%d不存在路径\n",v,i);
}
/* 请在这里填写答案 */
输入样例:
输入顶点数、边数,再依次输入每条边的2个邻接点编号(顶点编号从0开始)及权值。
5 7
0 1 10
0 4 100
0 3 30
1 2 50
2 4 10
3 2 20
3 4 60
输出样例:
若2个顶点不存在路径,则输出从3到7不存在路径
从0到1的最短路径长度为:10,路径为:0 1
从0到2的最短路径长度为:50,路径为:0 3 2
从0到3的最短路径长度为:30,路径为:0 3
从0到4的最短路径长度为:60,路径为:0 3 2 4
做题思路:
根据所学知识,要求最短路径的话,应该使用Dijkstra 算法来计算从源点 0 到图中所有其他顶点的最短路径。(Dijkstra 算法是一种贪心算法,用于计算带权有向图中单个源点到所有其他顶点的最短路径,要求所有边的权值非负。)
步骤:
初始化:创建距离数组dist用来记录源点到各顶点的最短路径长度,路径数组path用来记录最短路径中每个顶点的前驱,标记数组s用来记录已确定最短路径的顶点。
初始条件:设源点到自身的距离为 0,其他顶点的距离先初始化为无穷大。
迭代过程:每次从未确定最短路径的顶点中选择距离最小的顶点,并将其标记为已确定,然后更新其所有邻接顶点的距离值。
终止条件:所有顶点的最短路径都被确定或者无法继续更新。
最终代码如下:
void Dijkstra(MGraph g, int v) {
int n = g.n;
int dist[MAXV], path[MAXV], s[MAXV];
int min, i, j, u;
// 初始化
for (i = 0; i < n; i++) {
dist[i] = g.edges[v][i];
s[i] = 0;
if(g.edges[v][i] < INF)
{
path[i] = v;
}else{
path[i] = -1;
}
}
s[v] = 1;
path[v] = -1;
// 进行n-1次选择
for (i = 0; i < n - 1; i++) {
min = INF;
u = -1;
for (j = 0; j < n; j++) {
if (s[j] == 0 && dist[j] < min) {
u = j;
min = dist[j];
}
}
if (u == -1) break;
s[u] = 1;
// 更新距离和路径
for (j = 0; j < n; j++) {
if (s[j] == 0 && g.edges[u][j] < INF && dist[u] + g.edges[u][j] < dist[j]) {
dist[j] = dist[u] + g.edges[u][j];
path[j] = u;
}
}
}
Dispath(dist, path, s, n, v);
}