朴素dijkstra解决单源最短路问题
一. 单源最短路问题---Dijkstra(基于贪心)
A.边权为正
储存图的数据结构:邻接表(稀疏图)或邻接矩阵(稠密图)
算法需要的基本数据结构:
1.Set 集合 (实际用bool数组代替)用于存放已求得最短路径的顶点
2.dist[] : 存放对应顶点到源点的最短路径,初始态仅源点邻居存在有值,其余为∞
3.arcs[ i] [j]: i--j 的边权 ,无边则为∞ (这个数组无需修改)
步骤 :
1.初始化S集合为空,dist赋值初始态
2.从不属于Set集合的顶点中选出最近的一个顶点(dist[]值最小)加入Set(记为j号顶点)
3.更新源点到不属于Set集合的顶点集的所有dist[] ,将现有的dist[k]值跟 dist[j]+arcs[j] [k] 比较(注:j是刚确认的最小dist顶点,k为任意不属于Set的顶点)
基本原理:基于贪心,选出每一段的最短距离,最终的距离也是最短。
不能有负权边的原因:手动模拟会发现不满足贪心策略,根据朴素dijstra 每个顶点只会被更新一次最短路径,但是可能出现已经更完最短路的结点连接负权,而后却无法修改的情况。
题目:
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int dist[N];
int arcs[N][N];
bool st[N]; //set集合的具象表示
int n,m;
int dijkstra(){
memset(dist,0x3f,sizeof dist);
dist[1]=0; //1为源点
for(int i=0;i<n-1;i++){ //每次找一个t放入集合
int t=-1;
for(int j=1;j<=n;j++){
if(!st[j] && (t==-1 || dist[t] > dist[j])){ //找出不在Set中的最小的dist,记为t
t=j;
}
}
st[t]=true;
for(int j=1;j<=n;j++){
dist[j]=min(dist[j],dist[t]+arcs[t][j]); //更新所有不再Set中的顶点值,基于上一次的dist[j](min)
}
}
if(dist[n]==0x3f3f3f3f) return -1 ;//1到n的路径不存在
return dist[n];
}
int main()
{
memset(arcs,0x3f,sizeof arcs);
cin>>n>>m;
while (m -- ){
int x,y,z;
cin>>x>>y>>z;
arcs[x][y]=min(z,arcs[x][y]);
}
cout<<dijkstra();
return 0;
}