在家闲来无事,就把Dijkstra算法总结了一下,顺便加强巩固,希望对大家有帮助,理解的不够全面,希望大神们多多指点。
Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止(贪心的思想)。注意Dijkstra不能处理负权边。
基本步骤:
1,把所有的结点分成2个集合:
集合一:包含已经确定最短路径的结点;
集合二:包含尚未确定最短路径的结点。
2,初始化时,集合一只包含起点,集合二包含剩余的点。
3,用贪心的思想,按照最短路径长度递增的顺序把集合二中的结点加入集合一中,直到起点v0可到达的所有节点都在集合一中。在这个过程中不断更新最短路径。
4,直到v0可到达的所有的结点都在集合一种,这样就找到了v0到其他各点的最短路径。
如图:求v0到其他各点的最短路径。
(1)开始时,s1={v0},s2={v1,v2,v3,v4},v0到各点的最短路径是{0,10,&,30,100};
(2)在还未进入s1的顶点之中,最短路径为v1,因此s1={v0,v1},由于v1到v2有路径,因此v0到各点的最短路径更新为{0,10,60,30,100};
(3)在还未进入s1的顶点之中,最短路径为v3,因此s1={v0,v1,v3},由于v3到v2、v4有路径,因此v0到各点的最短路径更新为{0,10,50,30,90};
(4)在还未进入s1的顶点之中,最短路径为v2,因此s1={v0,v1,v3,v2},由于v2到v4有路径,因此v0到各点的最短路径更新为{0,10,50,30,60};
算法中最关键的有两步骤,步骤一:按照最短路径长度递增的顺序把集合二中的结点加入集合一。步骤二:更新路径。
下面是二个步骤的代码模板
(1)按照最短路径长度递增的顺序把集合二中的结点加入集合一
int map[maxn][maxn];//用来存储二结点之间的路径
int dist[maxn];//存储起点到达该结点的最短路径
bool vis[maxn];//标记结点,结点为1时表示在集合一中,结点结点为0时表示结点在集合二中
int n;
int getnext(){
int pos=-1, dis=INF,i; //INF为0x3f3f3f3f,代表两结点之间没路。
for(i=1;i<=n;++i)
if(!vis[i] && dist[i]<dis){
dis=dist[i];pos=i;
}
return pos;
}
(2) 更新路径
void Dijkstra()
{
int i,u,sum;
for(i=0;i<=n;++i){
vis[i]=0;dist[i]=INF;
}
u=1;dist[u]=0;//初始化起点,到自身的最短路径为0;
while(u!=-1){
vis[u]=true;//加入集合一中
for(i=0;i<=n;++i){
sum=dist[u]+map[u][i];
if(sum<dist[i])
dist[i]=sum;//更新最短路径
}
u=getnext();
}
return ;
}
以上只是最基本的模板,根据不同的题目情况需要更改。
PS:感谢正钢之前教给我的模板。