详解:Dijkstra算法求解单源最短路,存在负权边是不能用 dijkstra 算法求取最短路。
具体思路:从起点出发更新到其他点的路径值,选取点值最小的点不断更新,直至到达终点。
时间复杂度:O( (N+M)log(N) )
本博客主要以知识点复习为主。
#include<bits/stdc++.h>
using namespace std;
const int Max=100; //点的数目
const int INF=1e9; //设置最大值
int vis[Max]; //记录点是否被遍历过
int dis[Max]; //起点到达各点最短路
int c[Max][Max]; //记录权值
int path[Max]; //记录路径
int n,m; //点与边数目
void init() //初始化路径
{
for(int i=0;i<Max;i++)
{
dis[i]=INF;
path[i]=-1;
vis[i]=-1;
}
for(int i=0;i<Max;i++)
{
for(int j=0;j<Max;j++)
{
c[i][j]=INF;
}
c[i][i]=0;
}
}
void read() //读入数据
{
int u,v,w;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
c[u][v]=min(c[u][v],w); //重边选择最小边
c[v][u]=c[u][v];
}
}
void dijkstra(int s) //更新最小路径
{
for(int i=1;i<=n;i++)
{
dis[i]=c[s][i];
if(dis[i]!=INF)
{
path[i]=s;
}
}
dis[s]=0;
vis[s]=1;
path[s]=-1;
for(int i=2;i<=n;i++) //后续还有n-1个点
{
int temp=INF; //转移查找后续最小
int pos=s; //记录后续点
for(int j=1;j<=n;j++) //判断目前起点到达的路径最小点
{
if(vis[j]==-1&&dis[j]<temp)
{
temp=dis[j];
pos=j;
}
}
vis[pos]=1; //新的起点继续更新
for(int j=1;j<=n;j++)
{
if(vis[j]==-1&&c[pos][j]!=INF)
{
int temp=dis[pos]+c[pos][j];
if(temp<dis[j])
{
dis[j]=temp;
path[j]=pos;
}
}
}
}
}
void output(int e) //打印路径
{
if(path[e]==-1) //路径起始点
{
printf("%d",e);
}
else
{
output(path[e]);
printf("->%d",e);
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=-1)
{
init();
read();
dijkstra(1); //以起点1为例
printf("%d\n",dis[n]); //以终点n为例
//若输出INF 则下列函数无用 表示不连通
output(n);
printf("\n");
}
return 0;
}