/*********************
问题:
给定一个有向图G=(V,E)和源点s,求s到G中其它每个顶点的最短路径。
Dijkstra算法的具体实现方法:
(1)设置两个顶点的集合S和T
S中存放已经找到到源点s最短路径的顶点,初始时集合S中只有一个
顶点,即源点s。
T中存放当前还没有找到最短路径的顶点,即T=V-S。
(2)在集合T中选取当前长度最短的一条路径(s,...,v),将v加入到
集合S中,并修改源点s到集合T中每个顶点的最短路径长度;重复这一
步骤,直到所有的顶点都加入到集合S中(即S=V,T=空),算法就结束了。
Dijkstra算法的邻接矩阵实现,复杂度为O(V2)。
*********************/
#include<iostream>
//#include<climits>
//#include<string>
//#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=5; //最大顶点个数
const int M=10; //最大边数
const int inf=60000; //表示无穷大
int a[N+1][N+1]; //邻接矩阵
int d[N+1]; //记录源点s到顶点u的距离
int pre[N+1]; //记录源点s到顶点u的最短路径上u的前驱
bool vis[N+1]; //表示顶点u是否已经加入集合S中了
void dijkstra(int s){ //求源点s到其它顶点的最短路径
//初始化
for(int i=1; i<=N; ++i){
d[i] = inf; //把d[i]初始化为无穷大
pre[i] = -1; //每个顶点的父节点初始化为空
}
d[s] = 0;//s为源点
memset(vis, false, sizeof(vis)); //所有点都不在集合S中
//循环N次,以便于把每个点都加入集合S中
for(int i=1; i<=N; ++i){
int tmp = inf;
int k = 0;
//找出d值最小的点k
for(int j=1; j<=N; ++j){
if(!vis[j] && d[j]<tmp){
tmp = d[j];
k = j;
}
}
if(k==0) return; //没有点可以加入集合S中了,剩余点不可达
vis[k] = true; //把点k加入集合S
//更新k的邻居(不在集合S的)的d值
for(int j=1; j<=N; ++j){
if(!vis[j] && d[j]>d[k]+a[k][j]){
d[j] = d[k]+a[k][j];
pre[j] = k;
}
}
}
}
void print_path(int s, int v){
if(v==s){
printf("%d", s);
}
else{
if(pre[v] == -1)
printf("path no exist!\n");
else{
print_path(s, pre[v]);
printf("->%d", v);
}
}
}
int main()
{
freopen("shortpath.in", "r", stdin);
int u, v, w; //边(u, v)和权值w
for( int i=1; i<=N; ++i) //初始化邻接矩阵
for( int j=1; j<=N; ++j){
if(i==j) a[i][j] = 0;
else a[i][j] = inf;
}
for(int i=1; i<=M; ++i){
cin>>u>>v>>w;
a[u][v] = w;
a[v][u] = w;
}
int s=1; //选择的一个源点
dijkstra(s); //求源点s到其它顶点的最短路径
for(int v=1; v<=N; ++v){
if(v==s) continue;
printf("%d\t", d[v] ); //打印s到顶点v的最短路径长度
print_path(s, v); //打印出源点s到v的路径
printf("\n");
}
return 0;
}
dijkstra算法
最新推荐文章于 2023-02-01 16:04:02 发布