图论浅析--最短路之Dijkstra
个人总结,欢迎拍砖~
最短路径:对有权图G=(V,E),从一个源点s到汇点t有很多路径,其中路径上权和最小的路径,称s到t的最短路径。
单源最短路径:求源点s到其它所有点的最短路径问题。
Dijkstra
计算某一顶点到其它所有顶点的最短路径。需注意权值不能为负。
通过为每个顶点 v 保留目前为止所找到的从s到v的最短路径来工作。
算法原理:贪心。
复杂度:O(n^2)。 可使用优先队列优化
算法思想
对已求点集合S
1、在未求点中找到一个到源点权和最小的点k,权和为lowcost[k]。
2、把点k加到集合S中,同时修改其余各点j的 lowcost[j],是否经过k后变短,若变短则更新。
if(lowcost[k]+g[k][j]<lowcost[j])
lowcost[j]=g[k][j]+lowcost[k];
3、重复至更新完所有点。
过程演示
步骤 | v1 | v2 | v3 | v4 | v5 | v6 | v7 | 已选点集合S |
---|---|---|---|---|---|---|---|---|
1 | (v1,0)** | (v1,+∞) | (v1,+∞) | (v1,+∞) | (v1,+∞) | (v1,+∞) | (v1,+∞) | S={v1} |
2 | (v1,0)* | (v1,3)** | (v1,7) | (v1,5) | (v1,+∞) | (v1,+∞) | (v1,+∞) | S={v1,v2} |
3 | (v1,0)* | (v1,3)* | (v2,5)** | (v1,5) | (v2,9) | (v1,+∞) | (v1,+∞) | S={v1,v2,v3} |
4 | (v1,0)* | (v1,3)* | (v2,5)* | (v1,5)** | (v3,8) | (v1,+∞) | (v1,+∞) | S={v1,v2,v3,v4} |
5 | (v1,0)* | (v1,3)* | (v2,5)* | (v1,5)* | (v3,8) | (v4,7)** | (v4,13) | S={v1,v2,v3,v4,v6} |
6 | (v1,0)* | (v1,3)* | (v2,5)* | (v1,5)* | (v3,8)** | (v4,7)* | (v4,13) | S={v1,v2,v3,v4,v6,v5} |
7 | (v1,0)* | (v1,3)* | (v2,5)* | (v1,5)* | (v3,8)* | (v4,7)* | (v6,9)** | S={v1,v2,v3,v4,v6,v5,v7} |
Code
int n; //图的点数
int g[NUM][NUM]; //图的邻接矩阵
int lowcost[NUM]; //到各点的最短距离
bool vis[NUM]; //访问标记
int pre[NUM]; //最短路的前驱节点
void Dijkstra(int beg)
{
for(int i=0;i<n;i++)
{
lowcost[i]=INF;
vis[i]=false;
pre[i]=-1;
}
lowcost[beg]=0;
for(int j=0;j<n;j++)
{
int k=-1;
int Min=INF;
for(int i=0;i<n;i++)
{
if(!vis[i] && lowcost[i]<Min)
{
Min=lowcost[i];
k=i;
}
}
if(k==-1)break;
vis[k]=true;
for(int i=0;i<n;i++)
{
if(!vis[i] && lowcost[k]+g[k][i]<lowcost[i])
{
lowcost[i]=lowcost[k]+g[k][i];
pre[i]=k;
}
}
}
}
附:wikipedia的Dijkstra算法演示
版权声明:本文为博主原创文章,未经博主允许不得转载。