算法用途:一个点到其它各点的最短路径。(即单源最短路径)
算法图解:
构建图:
算法迭代过程:
算法核心思想:
设A到B的最短路径目前是dist(A->B),若新加入一个点U,使得dist(A->U)+dist(U->B)<dist(A->B),则更新当前AB的最短路径为dist(A->U->B)
示例程序:
#include<iostream>
#include<fstream>
using namespace std;
#define N 10000
#define MAX 100000099
int map[N][N];
int dist[N];
int n,m;
void input()
{
ifstream in("input.txt");
//n:几个点,m:几条路
in>>n>>m;
int p,q,len,i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
map[i][j]=MAX;
dist[i]=MAX;
}
for(i=0;i<m;i++)
{
in>>p>>q>>len;
if(len<map[p][q])
{
map[p][q]=len;
}
}
}
void dijkstra()
{
int s[N],newdist,i;
for(i=1;i<=n;i++)
{
dist[i]=map[1][i];
s[i]=0;
}
dist[1]=0;
s[1]=1;
for(i=2;i<=n;i++)
{
int j,temp=MAX;
int u=1;
//find next u
for(j=2;j<=n;j++)
{
if(!s[j]&&dist[j]<temp)
{
u=j;
temp=dist[j];
}
}
s[u]=1;
//update
for(j=2;j<=n;j++)
{
if(!s[j]&&map[u][j]<MAX)
{
newdist=dist[u]+map[u][j];
if(newdist<dist[j])
dist[j]=newdist;
}
}
}
}
void output()
{
for(int i=2;i<=n;i++)
{
cout<<"第1个点到第"<<i<<"个点的最短路径是:"<<dist[i]<<endl;
}
}
int main()
{
input();
dijkstra();
output();
system("pause");
return 0;
}
Input:
5 7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
缺点:
Dijkstra算法要求各边的权值非负
原因:
假设目前OA,OB分别是O点到A点、O点到B点的最短路径,若BA的权值为负,则有可能出现OB+BA<OA,那么OA就不是O点到A点的最短路径了,与假设不符,不成立。
实质:
Dijkstra是贪心算法,每一次加入的新点必然是符合当前最短路径的一点,若后面没加入的点权值有负值,就可能影响到新加入的点的最短路径值,而这是不允许的。