所谓单源最短路径,是指从一个顶点(源点)出发到其他各顶点的最短路径,即给定有向网G和源点Vk,求从Vk到G中其他各顶点Vj(j=1,2,····,n,j!=k)的最短路径。

迪杰斯特拉提出了一种按路径长度递增的次序产生最短路径的算法。其基本思想是,把网中所有顶点分成两组,第一组是已确定最短路径的顶点集合S,第二组是尚未确定最短路径的顶点集合V;把V中的顶点按最短路径长度递增的顺序逐个添加到S中,添加过程中始终保持从Vk到S中每个顶点的最短路径长度都不大于从Vk到V中任何顶点的最短路径长度,直到从Vk出发可以到达的顶点都在S中为止。

一开始,S中只有顶点Vk,其余顶点在V中。引入一维数组dist,用dist[i]表示当前时刻所找的从源点到每个中点Vi的最短路径长度;其初始值为dis[k]=0;若存在弧(vk,vi),则dist[i]为其弧上的权值,否则从Vk到Vi无弧时dist[i]=max。然后每次从V中的顶点选取一个dist值最小的顶点Vj(dist[j]=min{dist[i]|Vi属于V})加入到S中,并对V中顶点的dist值进行相应的修改,即若以加入S中的顶点Vj作为中间顶点使得V中某顶点的dist值更小时要相应地修改该顶点的dist值。这样从V中选一个顶点加入到S中,对V中的顶点的dist值修改一遍,只需做n-1次就可求得Vk到其余各顶点的最短路径。

在求最短路径的过程中,最短路径长度已记在dist数组中,同时需要把路径也记下来。为此设一个一维数组pre,pre[i]存放从Vk到Vi的路径上Vi前一个顶点的序号;若Vk到Vi无路径可达,则vi的前一个顶点序号用0表示(即pre[i]=0)。在算法结束时,沿着顶点Vi对应的pre[i]向前追溯就能确定从Vk到Vi的最短路径,其最短路径长度为dist[i].

设有向网用邻接矩阵a表示,a[i,j]表示弧(Vi,Vj)上的权值,无弧(Vi,Vj)时a[i,j]为max;a[i,j]=0,当Vi进入S中时,用a[i,j]=1来标识。求有向图中从顶点Vk出发到其他各顶点的最短路径的Dijkstra算法如下:


void dijkstra(int a[][],int k,int pre[],int dist[],int n)//求用邻接矩阵a表示的有向网中从Vk到其他各顶点最短路径
{
    int i,j,p,min;//定义局部变量
    for(i=1;i<=n;i++)//数组dist,pre初始化
    {
        dist[i]=a[k][i];
        if(dist[i]<max)
            pre[i]=k;
        else 
            pre[i]=0;
    }
    pre[k]=0;
    dist[k]=0;
    a[k][k]=1;//Vk加入S中控制n-1次按长度递增产生最短路径
    for(p=1;p<=n-1;p++)
    {
        min=max;//预置最短路径长度为max
        j=-1;//设结束标志
        for(i=1;i<=n;i++)
            if(a[i][i]==0&&dist[i]<min)
            {
                j=i;
                min=dist[i];//在V中选dist最小的点
            }
        if(j==-1) break;//已无顶点可加入S,退出
        else 
        {
            a[j][j]=1;//把选出的顶点Vj加入S中
            for(i=1;i<=n;i++)//更新V中顶点的dist和pre值
                if(a[i][i]==0&&(min+a[j][i]<dist[i]))
                {
                    dist[i]=min+a[j][i];
                    pre[i]=j;
                }
        }
    }
}//dijkstra