原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html

单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径。在弄清楚如何求算单源最短路径问题之前,必须弄清楚最短路径的最优子结构性质。

一.最短路径的最优子结构性质

该性质描述为:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径。下面证明该性质的正确性。

假设P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)。而P(k,s)不是从k到s的最短距离,那么必定存在另一条从k到s的最短路径P'(k,s),那么P'(i,j)=P(i,k)+P'(k,s)+P(s,j)<P(i,j)。则与P(i,j)是从i到j的最短路径相矛盾。因此该性质得证。

二.Dijkstra算法

由上述性质可知,如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点。那么(Vi...Vk)也必定是从i到k的最短路径。为了求出最短路径,Dijkstra就提出了以最短路径长度递增,逐次生成最短路径的算法。譬如对于源顶点V0,首先选择其直接相邻的顶点中长度最短的顶点Vi,那么当前已知可得从V0到达Vj顶点的最短距离dist[j]=min{dist[j],dist[i]+matrix[i][j]}。根据这种思路,

假设存在G=<V,E>,源顶点为V0,U={V0},dist[i]记录V0到i的最短距离,path[i]记录从V0到i路径上的i前面的一个顶点。

1.从V-U中选择使dist[i]值最小的顶点i,将i加入到U中;

2.更新与i直接相邻顶点的dist值。(dist[j]=min{dist[j],dist[i]+matrix[i][j]})

3.知道U=V,停止。

代码实现:

/*Dijkstra求单源最短路径 2010.8.26*/

#include <iostream>
#include<stack>
#define M 100
#define N 100
using namespace std; typedef struct node
{
int matrix[N][M]; //邻接矩阵
int n; //顶点数
int e; //边数
}MGraph; void DijkstraPath(MGraph g,int *dist,int *path,int v0) //v0表示源顶点
{
int i,j,k;
bool *visited=(bool *)malloc(sizeof(bool)*g.n);
for(i=0;i<g.n;i++) //初始化
{
if(g.matrix[v0][i]>0&&i!=v0)
{
dist[i]=g.matrix[v0][i];
path[i]=v0; //path记录最短路径上从v0到i的前一个顶点
}
else
{
dist[i]=INT_MAX; //若i不与v0直接相邻,则权值置为无穷大
path[i]=-1;
}
visited[i]=false;
path[v0]=v0;
dist[v0]=0;
}
visited[v0]=true;
for(i=1;i<g.n;i++) //循环扩展n-1次
{
int min=INT_MAX;
int u;
for(j=0;j<g.n;j++) //寻找未被扩展的权值最小的顶点
{
if(visited[j]==false&&dist[j]<min)
{
min=dist[j];
u=j;
}
}
visited[u]=true;
for(k=0;k<g.n;k++) //更新dist数组的值和路径的值
{
if(visited[k]==false&&g.matrix[u][k]>0&&min+g.matrix[u][k]<dist[k])
{
dist[k]=min+g.matrix[u][k];
path[k]=u;
}
}
}
} void showPath(int *path,int v,int v0) //打印最短路径上的各个顶点
{
stack<int> s;
int u=v;
while(v!=v0)
{
s.push(v);
v=path[v];
}
s.push(v);
while(!s.empty())
{
cout<<s.top()<<" ";
s.pop();
}
} int main(int argc, char *argv[])
{
int n,e; //表示输入的顶点数和边数
while(cin>>n>>e&&e!=0)
{
int i,j;
int s,t,w; //表示存在一条边s->t,权值为w
MGraph g;
int v0;
int *dist=(int *)malloc(sizeof(int)*n);
int *path=(int *)malloc(sizeof(int)*n);
for(i=0;i<N;i++)
for(j=0;j<M;j++)
g.matrix[i][j]=0;
g.n=n;
g.e=e;
for(i=0;i<e;i++)
{
cin>>s>>t>>w;
g.matrix[s][t]=w;
}
cin>>v0; //输入源顶点
DijkstraPath(g,dist,path,v0);
for(i=0;i<n;i++)
{
if(i!=v0)
{
showPath(path,i,v0);
cout<<dist[i]<<endl;
}
}
}
return 0;
}

【转】Dijkstra算法(单源最短路径)的更多相关文章

  1. Dijkstra算法——单源最短路径问题

    学习一个点到其余各个顶点的最短路径--单源最短路径 Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向 ...

  2. Dijkstra求解单源最短路径

    Dijkstra(迪杰斯特拉)单源最短路径算法 Dijkstra思想 Dijkstra是一种求单源最短路径的算法. Dijkstra仅仅适用于非负权图,但是时间复杂度十分优秀. Dijkstra算法主 ...

  3. Dijkstra算法——单源最短路算法

    一.介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他各个节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 适用于有 ...

  4. hdu 2680 最短路径(dijkstra算法+多源最短路径单源化求最小值)这题有点意思

    Choose the best route Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  5. 单源最短路径Dijkstra算法,多源最短路径Floyd算法

    1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...

  6. 单源最短路径——dijkstra算法

    dijkstra算法与prim算法的区别   1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...

  7. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

    一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...

  8. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)

    一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...

  9. Dijkstra 单源最短路径算法

    Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...

随机推荐

  1. RESTLET开发实例(一)基于JAX-RS的REST服务

    RESTLET介绍 Restlet项目为“建立REST概念与Java类之间的映射”提供了一个轻量级而全面的框架.它可用于实现任何种类的REST式系统,而不仅仅是REST式Web服务. Restlet项 ...

  2. LoadRunner检查点实战

    码农博客 即将到期,现将博客中部分文章转载到博客园.转载时略有删减. 一.为什么要使用检查点 为什么要使用检查点,那就要说明一下LR如何判断脚本是否执行成功. LR判断脚本是否执行成功是根据服务器返回 ...

  3. 【windows核心编程】使用远程线程注入DLL

    前言 该技术是指通过在[目标进程]中创建一个[远程线程]来达到注入的目的. 创建的[远程线程]函数为LoadLibrary, 线程函数的参数为DLL名字, 想要做的工作在DLL中编写.  示意图如下: ...

  4. OnItemClickListener 的参数详解(转)

    转载地址:http://blog.iamzsx.me/show.html?id=147001 我们在使用ListView的时候,一般都会为ListView添加一个响应事件android.widget. ...

  5. PHP中我经常容易混淆的三组函数

    原文:http://www.ido321.com/1252.html 一.htmlentities() 和htmlspecialchars() 1.htmlentities() 1.1  功能:把字符 ...

  6. reverse the string word by word

    题目:Given an input string, reverse the string word by word. For example,Given s = "the sky is bl ...

  7. 线段相交 poj 1066

    // 线段相交 poj 1066 // 思路:直接枚举每个端点和终点连成线段,判断和剩下的线段相交个数 // #include <bits/stdc++.h> #include <i ...

  8. 微软Azure已开始支持hadoop--大数据云计算

    微软Azure已开始支持hadoop,对于有需要弹性大数据运算的公司可能是个好消息.据悉,近期微软已提供一个预览版的Azure HDInsight(Hadoop on Azure)服务,运行在Linu ...

  9. 数位DP专题

    这周开始刷数位DP,在网上找到一份神级数位DP模板,做起题目来爽歪歪. http://www.cnblogs.com/jffifa/archive/2012/08/17/2644847.html in ...

  10. 【转】Objective-C代码注释和文档输出的工具和方法

    http://blog.xcodev.com/blog/2013/11/01/code-comment-and-doc-gen-tools-for-objc/ 代码注释可以让代码更容易接受和使用,特别 ...