Dijkstra
算法用来解决赋权图的单源最短路径问题。Dijkstra是典型的Greed,基本思想就是BFS。每个阶段在所有未知顶点里选择Dn值最小的点a。把A标记为已知点。然后从a出发赋所有与该点连通的点(e.g b)的Db=Da+AB间的权值。在赋值时,如果Da+AB>Db,说明之前有一条更短的连向B的路径,则保持原有Db。每次成功的改变Dn后,将Pn的值改为使之Dn改变的点的序号。即如果赋值Db=Da+AB,则Pr=a。Pn起指向作用,以反向找到最短路劲。初始状态下,所有点都标记为未知,Dn赋一个极大的值,Pn标为0。将起点的Dn赋0。
效率方面,因为每次都要从都要从Dn里找最小Dv,所以时间效率是V2的。如果是稠密图,基本上程序比较优了。关于稀疏图用优先队列,二叉堆优化神马的,以后再看...如果需要每个顶点作为源的所有最短路,在稠密图下,Floyd比循环n次Dijkstra稍快,且简洁。
程序实现:
/*Dijkstra 邻接表*/
#include<stdio.h>
#include<string.h>
#include<iostream>
#define INF 0xfffff
#define MAXV 100
using namespace std;
int dist[MAXV]; //Dn,当前点到源的最短路长
int prev[MAXV]; //Pn,当前点前驱
int visited[MAXV]; //访问标记
int map[MAXV][MAXV]; //图
int v,e; //v 顶点数 e边数
int Dijkstra(int s) //传入s起点
{
for(int j=1; j<=v; ++j)
{
dist[j] = INF;
}
memset(prev,0,sizeof(dist));
memset(visited,false,sizeof(visited));
dist[s]=0;
for(int i=2;i<=v;i++)
{
int mindist=INF,minp=0;
for(int j=1;j<=v;j++)
{
if(!visited[j])
{
if(mindist>dist[j])
{
mindist=dist[j];
minp=j;
}
}
}
visited[minp]=1;
for(int k=1;k<=v;k++)
{
if(!visited[k]&&map[minp][k]<INF)
{
int newdist=map[minp][k]+dist[minp];
if(newdist<dist[k])
{
dist[k]=newdist;
prev[k]=minp;
}
}
}
}
return 0;
}