单源最短路径(Dijkstra)
问题描述:求解从源点到所有点的最短路径。
Dijkstra过程:
(1)G=(V,E),设置待加入顶点集合s,开始时集合s中只有源点,源点记录为v,
(2)计算出从源点v到G中所有顶点且只能经过s中顶点的距离。并且用dist数组记录当前每个顶点所对应的最短特殊路径长度。
(3)将dist数组中最小的顶点加入s中,
(4)重复步骤2和原来比较如果小于则修改否则不变。重复3.直到G中所有顶点加入s中。
贪心选择为:从V-S中选择具有最短特殊路径的顶点u,从而确定源到u的最短路径长度dist[u]。
例如:
算法如下:
//prev:记录当前顶点前缀顶点,dist:记录当前顶点最短路径(源点到当前顶点)
//a:当前所有顶点直达边数组。
//s记录当前顶点加入没有,1表示加入,0表示未加入。
public static void dijkstra(int v,float[][]a,float dist[],int prev[])
{
int n=dist.length-1;
if(v<1||v>n)return;
boolean s[]=new boolean[n+1];
//初始化
for(int i=1;i<=n;i++)
{
dist[i]=a[v][i];//初始化dist
s[i]=false;//默认这些节点还没有加入s中。
if(dist[i]==Float.MAX_VALUE) prev[i]=0;//如果不可直达前缀顶点赋值为0。
else prev[i]=v;
}
dist[v]=0;s[v]=true;
for(int i=1;i<n;i++){//控制找最小和调整的次数
float temp=Float.MAX_VALUE;
int u=v;//当前加入的边
for(int j=1;j<n;j++)//确定加入哪个点。
{
if((!s[j])&&dist[j]<temp)
u=j;
temp=dist[j];
}
s[u]=true;
for(int j=1;j<=n;j++){//加入新点之后的调整
if((!s[j])&&(a[u][j]<Float.MAX_VALUE))//未加入且到新加入点有直达边
{
float newdist=dist[u]+a[u][j];//计算出源点到顶点的距离
if(newdist<dist[j])//新加入点后源点到顶点小于原先的值
{
dist[j]=newdist;
prev[j]=u;
}
}
}
}
}