给定带权有向图G =(V,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到所有其它各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。
1、算法基本思想
Dijkstra(迪杰斯特拉)算法是解单源最短路径问题的贪心算法。
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组m记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组m作必要的修改。一旦S包含了所有V中顶点,m就记录了从源到所有其它顶点之间的最短路径长度。(http://www.cnblogs.com/chinazhangjie/archive/2010/11/23/1885330.html)
如下图所示:
代码如下:
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("in.txt");
#define LL 20
int a[LL][LL];
bool visited[LL];
int m[LL];
void Dijkastra(int n)
{
int i,j,min,t;
visited[0]=true;
m[0]=0;
int count = 1;
int last = 0;
while(count < n)
{
min = t = 10000;
for(j=1;j<n;j++)
{
if( !visited[j])
{
if(a[last][j])
{
t =a[last][j]+m[last];
if(t<m[j] || m[j]==0) m[j]=t;
}
if(m[j]<min && m[j]!=0){min=m[j];i=j;}
cout<<"j:"<<j<<" i:"<<i<<" last:"<<last<<" a[last][j]:"<<a[last][j]<<" m[last]:"<<m[last]<<" m[j]:"<<m[j]<<endl;
}
}
cout<<"--- i :"<<i<<" m[i]:"<<min<<endl;
visited[i]=true;
last=i;
m[last]=min;
count++;
}
return;
}
int main()
{
int n;
fin>>n;
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
fin>>a[i][j];
}
}
memset(visited,0,sizeof(int)*LL);
memset(m,0,sizeof(int)*LL);
Dijkastra(n);
for(i=1;i<n;i++)
{
cout<<"1-->"<<i+1<<" : "<<m[i]<<endl;
}
return 0;
}
输入文件: in.txt
5(第一个)
0 10 0 30 100
0 0 50 0 0
0 0 0 0 10
0 0 20 0 60
0 0 0 0 0
5(第二个)
0 4 2 0 0
0 0 3 2 3
0 1 0 4 5
0 0 0 0 0
0 0 0 1 0
输出结果:
(第一个)
(第二个)