单源最短路径 Dijkastra算法

       给定带权有向图G =(V,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到所有其它各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。

1、算法基本思想

Dijkstra(迪杰斯特拉)算法是解单源最短路径问题的贪心算法。

其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集S当且仅当从源到该顶点的最短路径长度已知。

初始时,S中仅含有源。设uG的某一个顶点,把从源到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

如下图所示:

单源最短路径 Dijkastra算法_第1张图片

代码如下:

   

#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 

输出结果:

(第一个)

单源最短路径 Dijkastra算法_第2张图片

(第二个)

单源最短路径 Dijkastra算法_第3张图片

你可能感兴趣的:(算法)