单源最短路径(两种方法)

合集下载

最短路径单源最短路径问题单源最短路径问题

最短路径单源最短路径问题单源最短路径问题

¾ 规律:当按长度增序生成从源s到其它顶点的最短路径时,则当前正 在生成的最短路径上除终点外,其余顶点的最短路径均已生成
¾ 例子:当求0到2的最短路径时,则该路径<0,3,2>上顶点0,3的最短路
径在此前已生成
2
§7.6.1 单源最短路径问题
约定 从源s到终点v的最短路径简称为v的最短路径,SP(v) s到v的最短路径长度简称为v的最短距离,SD(v) 红点集S:最短距离已确定的顶点集合 白点集V-S:最短距离尚未确定的顶点集合
6
1
§7.6.1 单源最短路径问题
例子
10 10
1
0
0 100 100
30 4
∞2
3 30
10 10
1
50
60 2
0 0 100
100 30 4
3 30
10 10
1
50 2
0 0
30
4 90
60
20 3 30
0
10 0
10 1
30
10
4 60
50 2 20 3 30
10 0 1 30 50 10
2 20
100
4 60 3
最短距离:红色 估计距离:白色 依次求出的最短距离为: 1) D[0]=0 2) D[1]=10,调整顶点2 3) D[3]=30,调整顶点2,4 4) D[2]=50,调整顶点4 5) D[4]=60
¾ 最短路径树:各顶点的最短路径(实线)总是一棵以源点为根的树,称之
为最短路径树。
算法思想- Dijkstra(1972图灵奖得主) 基于上述观察 初始化:仅已知源s的最短距离SD(s)=0,故红点集S={s}; 扩充红点集:算法的每一步均是在当前白点集中选一最短距离最小的白点 来扩充红点集,以保证算法是按长度增序来产生各顶点的最短路径; 结束:当前白点集空或仅剩下最短距离为∞的白点为止。注:若s到某白 点的路径不存在,可假设该白点的最短路径是一条长度为∞的虚拟路径。

单源最短路径Dijkstra算法

单源最短路径Dijkstra算法

单源最短路径算法设计问题描述:一个带有权值的有向图G=(V,E) ,其中每条边的权是一个非负实数。

另外,还给定V 中的一个源点。

现在我们要计算从源到所有其他各顶点通路的权值和最小值,继承做单源最短路径问题。

输入:顶点个数权值输出:最短路径及权值算法描述:Dijkstra提出按各顶点与源点v间的路径长度的递增次序,生成到各顶点的最短路径的算法。

既先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从源点v 到其它各顶点的最短路径全部求出为止。

算法设计:将图G中所有的顶点V分成两个顶点集合S和T。

以v为源点已经确定了最短路径的终点并入S集合中,S初始时只含顶点v ,T则是尚未确定到源点v最短路径的顶点集合。

然后每次从T集合中选择S集合点中到T路径最短的那个点,并加入到集合S中,并把这个点从集合T删除。

直到T集合为空为止1、选一顶点v为源点,并视从源点v出发的所有边为到各顶点的最短路径(确定数据结构:因为求的是最短路径,所以①就要用一个记录从源点v到其它各顶点的路径长度数组dist[],开始时,dist是源点v到顶点i的直接边长度,即dist中记录的是邻接阵的第v行。

②设一个用来记录从源点到其它顶点的路径数组path[],path中存放路径上第i个顶点的前驱顶点)。

2、在上述的最短路径dist[]中选一条最短的,并将其终点(即<v,k>)k加入到集合s中。

3、调整T中各顶点到源点v的最短路径。

因为当顶点k加入到集合s中后,源点v到T中剩余的其它顶点j就又增加了经过顶点k到达j的路径,这条路径可能要比源点v到j 原来的最短的还要短。

调整方法是比较dist[k]+g[k,j]与dist[j],取其中的较小者。

4、再选出一个到源点v路径长度最小的顶点k,从T中删去后加入S中,再回去到第三步,如此重复,直到集合S中的包含图G的所有顶点。

举例:初始情况第一次松弛,选取A顶点第二次松弛,C的估算距离最小,选取C顶点:第三次松弛,E的估算距离最小,选取E:第四次松弛,B的估算距离最小,选取B:第五次松弛:(最后一个点,完成程序:1 #include <iostream>2 #include <cstdio>3 #include <vector>4 #include <queue>5using namespace std;67#define maxn 110 //最大顶点个数8int n; //顶点个数910struct arcnode //边结点11 {12int vertex; //与表头结点相邻的顶点编号13int weight; //连接两顶点的边的权值14 arcnode * next; //指向下一相邻接点15 arcnode() {}16 arcnode(int v,int w):vertex(v),weight(w),next(NULL) {}17 };1819struct vernode //顶点结点,为每一条邻接表的表头结点20 {21int vex; //当前定点编号22 arcnode * firarc; //与该顶点相连的第一个顶点组成的边23 }Ver[maxn];2425void Init() //建立图的邻接表需要先初始化,建立顶点结点26 {27for(int i = 1; i <= n; i++)28 {29 Ver[i].vex = i;30 Ver[i].firarc = NULL;31 }32 }3334void Insert(int a, int b, int w) //尾插法,插入以a为起点,b为终点,权为w的边,效率不如头插,但是可以去重边35 {36 arcnode * q = new arcnode(b, w);37if(Ver[a].firarc == NULL)38 Ver[a].firarc = q;39else40 {41 arcnode * p = Ver[a].firarc;42if(p->vertex == b)43 {44if(p->weight > w)45 p->weight = w;46return ;47 }48while(p->next != NULL)49 {50if(p->next->vertex == b)51 {52if(p->next->weight > w)53 p->next->weight = w;54return ;55 }56 p = p->next;57 }58 p->next = q;59 }60 }61void Insert2(int a, int b, int w) //头插法,效率更高,但不能去重边62 {63 arcnode * q = new arcnode(b, w);64if(Ver[a].firarc == NULL)65 Ver[a].firarc = q;66else67 {68 arcnode * p = Ver[a].firarc;69 q->next = p;70 Ver[a].firarc = q;71 }72 }73struct node //顶点节点,保存id和到源顶点的估算距离,优先队列需要的类型74 {75int id; //源顶点id和估算距离76int w;77 friend bool operator<(node a, node b) //因要实现最小堆,按升序排列,因而需要重载运算符,重定义优先级,以小为先78 {79return a.w > b.w;80 }81 };8283#define INF 0xfffff //权值上限84int parent[maxn]; //每个顶点的父亲节点,可以用于还原最短路径树85bool visited[maxn]; //用于判断顶点是否已经在最短路径树中,或者说是否已找到最短路径86 node d[maxn]; //源点到每个顶点估算距离,最后结果为源点到所有顶点的最短路。

单源最短路径

单源最短路径

单源最短路径问题[Dijkstra实现]一、问题带权有向图G(E,V), 找出从给定源顶点s到其它顶点v的权最小路径。

“最短路径” = 最小权二、问题求解:求1到5的最短路径值?三、执行过程:如果大家对这个问题的要求还不是很明白的话那么我再带着大家走一遍:第一次:从1-->2:10 此时从1-->3没有路径所有是无穷大1-->4:30 1-->5:100那么我们发现这一组组最小的是10也就是2这一点,所以我们再把2这一点加到集合里面来,那么2这一点就可以当作一个桥来用,第二次:此时我们再从1à3就可以通过1-->2-->3:60其他的1-->4:301-->5:100 可以发现此时最小的应该是3,所以我们再把3这一点加入到这个集合里面来,如此重复的去做这些事情,到最后可以发现1à5的最短路径应该是60(1-->4-->3-->5)四、Dijkstra伪代码:int dijkstra(int s,int t) {初始化S={空集}d[s] = 0; 其余d值为正无穷大while (NOT t in S){取出不在S中的最小的d[i];for (所有不在S中且与i相邻的点j)if (d[j] > d[i] + cost[i][j]) d[j] = d[i] + cost[i][j]; ( “松弛”操作” )S = S + {i}; //把i点添加到集合S里}return d[t];}为何松弛操作:也就是说如果1-->3这点的值为dist[3]>dist[2]+map[2][3]那么dist[3]=dits[2]+map[2][3]五、代码实现:#include <iostream>using namespace std;#define MAX 9999999#define LEN 210int map[LEN][LEN]; //某点到某点两点间的的距离int dist[LEN]; //记录当前点到源点的最短路径长度int mark[LEN]; //加入进来的点的集合//初始化map为正无穷大void init(){int i,j;for(i=0;i<LEN;i++){for(j=0;j<LEN;j++){map[i][j]=MAX;}}//n:多少条路start:起始点void myDijstra(int n,int start){int i,j,min,k;for(i=1;i<=n;i++){mark[i]=0;//没有点加入dist[i]=map[start][i];//初始}mark[start]=1;//把起始点加进来dist[start]=0;for(i=1;i<=n;i++){min=MAX;for(j=1;j<=n;j++){if(!mark[j] && dist[j]<min){ //取出不在mark里的最小的dist[i] min=dist[j];k=j;//标记}}if(min==MAX)break;mark[k]=1;//把K加进来//做松弛操作for(j=1;j<=n;j++){if(!mark[j] && dist[j]>dist[k]+map[k][j]){dist[j]=dist[k]+map[k][j];}}}}int main(){int i,j,n,line;int a,b,d;cin>>n>>line; //输入点和边for(i=0;i<line;i++){cin>>a>>b>>d; //输入各边的权值if(map[a][b]>d){map[a][b]=map[b][a]=d;}}myDijstra(n,1);//调用方法//输出1到5的最短路径cout<<dist[5]<<endl;return 0;}Dijkstra算法(单源最短路径)单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径。

最短路径算法

最短路径算法

§distance[j]=distance[u]+G[u][j]; §path[j]=u; §}}}
2、算法的正确性和计算复杂性
(1)贪心选择性质 (2)最优子结构性质 (3)计算复杂性 对于具有n个顶点和e条边的带权有向图,如果用 带权邻接矩阵表示这个图,那么Dijkstra算法的主循 环体需要 O (n)时间。这个循环需要执行n-1次,所以完 O(时间。算法的其余部分所需要时间不 n2 ) 成循环需要 O(n 2 ) 超过 。
7.5所有点对的最短路径问题
§对于一个各边权值均大于0的有n个顶点的带 权有向图G=(V,E),求所有顶点之间的最短 路径和最短距离。
图的邻接矩阵表示法
1
1 1
3
0 2
9
2
2
8 9 6
V = 2
3
L= 8 0 6
1 ∞ 0
(b )
(a )
复习Dijkstra算法
其基本思想是,设置顶点集合S并不断地作 基本思想是 设置顶点集合S 贪心选择来扩充这个集合 一个顶点属于集合S 来扩充这个集合。 贪心选择来扩充这个集合。一个顶点属于集合S 当且仅当从源到该顶点的最短路径长度已知。 当且仅当从源到该顶点的最短路径长度已知。 初始时, 中仅含有源点。 初始时,S中仅含有源点。设u是G的某一个 顶点,把从源点到u且中间只经过S 顶点,把从源点到u且中间只经过S中顶点的路称 为从源到u的特殊路径,并用数组dist distance记录 为从源到u的特殊路径,并用数组dist 记录 当前每个顶点所对应的最短特殊路径长度。 当前每个顶点所对应的最短特殊路径长度。 Dijkstra算法每次从 算法每次从V Dijkstra算法每次从V-S中取出具有最短特殊路 长度的顶点u 添加到S 长度的顶点u,将u添加到S中,同时对数组 distance作必要的修改。一旦S包含了所有V中 作必要的修改。 dist 作必要的修改 一旦S包含了所有V 顶点,distance就记录了从源到所有其它顶点 顶点,dist 就记录了从源到所有其它顶点 之间的最短路径长度。 之间的最短路径长度。

单源最短路径

单源最短路径
2018年4月7日
4.5 单源最短路径
1
一、问题的提法及应用背景
(1)问题的提法——给定带权有向图G=(V,E),其中 每条边的权是非负实数。另外,还给定V中的一个顶 点,称为源。现在要计算从源到所有其他各顶点的
2018年4月7日
最短路长度。这里路的长度是指路上各边权之和。
这个问题通常称为单源最短路径问题。 (2)应用背景——管道铺设、线路安排、厂区布局、 设备更新等。
10
1
2018年4月7日
100 30
dist[2]=10
2
50 10
5
60
dist[4]=30
dist[5]=60 dist[3]=50
3
20
4
源点1到其它各点的最短距离分别为: Dist[2]=10 dist[3]=50 dist[4]=30
dist[5]=60
9
DIJKSTRA 算法的迭代过程
2
二、 DIJKSTRA(迪科斯彻)算法基本思想
其基本思想是,设置顶点集合S并不断地作贪心选择来
2018年4月7日
扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点
的最短路径长度已知。 初始时,S中仅含有源。设u是G的某一个顶点,把从源
到u且中间只经过S中顶点的路称为从源到u的特殊路径,并
用数组dist记录当前每个顶点所对应的最短特殊路径长度。 Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u, 将u添加到S中,同时对数组dist作必要的修改。一旦S包含 了所有V中顶点,dist就记录了从源到所有其他顶点之间的 最短路径长度。
11
dist[v]=0; /*源点到源点的最短路径为0*/ s[v]=true; /*源点v在集合S中,为下面循环中源点不参加比较做准备*/ /*中心部分*/ for(i=1;i<n;i++) { float temp=Float.MAX_VALUE; int u=v; /*找出一个剩余结点中到源点最短的结点*/ for(j=1;j<=n;j++) if((!s[j]) && (dist[j]<temp)) /*如果该点不是源点并 且源点到j点路径是最短*/ { u=j; /*u记录最短路径的点*/ temp=dist[j]; /*记录源点到j点的最短路径*/ } s[u]=true; /*u点是下面进行比较的点*/

单源最短路径算法小总结

单源最短路径算法小总结

单源最短路径算法⼩总结注意下⾯的模板有的并没有去设定具体的⽆法到达的极限值,也没有考虑极限相加爆表的情况,如果可以的话,最好还是把dis数组定义成long longFloyd算法(仅仅四⾏的算法)Floyd算法仅仅四⾏就能解决问题但是时间复杂度达到了感⼈的O(n^3),唯⼀的有点是能够输出任意两点之间的最⼩路径,这或许是他唯⼀的⽤途了吧。

伪代码初始化赋值如果i==j为0其余为inf建图Floyd四⾏代码输出代码模板#include <bits/stdc++.h>using namespace std;int G[10005][10005];int main(){//n为节点数,m为边的条数int n,m;cin>>n>>m;//初始化,如果i==j那么G[i][j]就是0for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)G[i][j]=i==j?0:999999999;//建图while(m--){int t1,t2,t3;cin>>t1>>t2>>t3;G[t1][t2]=t3;}//Floyd算法的核⼼,4⾏代码解决for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)G[i][j]=min(G[i][j],G[i][k]+G[k][j]);//输出答案for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)cout<<G[i][j]<<" ";cout<<endl;}return 0;}Floyd可以解决任意两个节点之间的最短路,⽽且在稀疏图有着还可以的时间复杂度Dijkstra算法⽆优化原始版本时间复杂度的进⼀步的降低,能够算出源节点到各个节点之间的最短路伪代码初始化赋值如果i==j为0其余为inf建图初始化dis数组与bk数组bk[s]=1;循环n次寻找离要找节点最近的节点尝试每个节点是否能够被这个最近的节点松弛循环结束输出dis数组代码模板#include <bits/stdc++.h>using namespace std;int G[10010][10010];int dis[10010];int bk[10010];int main(){int n,m,s;cin>>n>>m>>s;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)G[i][j]=i==j?0:999999999;while(m--){int t1,t2,t3;cin>>t1>>t2>>t3;G[t1][t2]=t3;}for(int i=1;i<=n;i++)dis[i]=G[s][i];memset(bk,0,sizeof(bk));bk[s]=1;for(int i=1;i<=n;i++){int x,minn=999999999;for(int j=1;j<=n;j++)if(dis[j]<minn&&!bk[j])minn=dis[x=j];bk[x]=1;for(int j=1;j<=n;j++)dis[j]=min(dis[j],dis[x]+G[x][j]);}for(int i=1;i<=n;i++)cout<<dis[i]<<" ";return 0;}复杂度O(n^2)vector建图优化因为我们⽤邻接矩阵建图很有可能会爆内存,所以可以采⽤vector数组建图优化。

求解单源最短路径问题的算法

求解单源最短路径问题的算法

求解单源最短路径问题的算法
求解单源最短路径问题的算法有多种,下面列举了几种常见的算法:
1. Dijkstra算法:通过维护一个距离数组,不断更新起始点到其他节点的最短路径长度。

核心思想是每次选择距离起始点最近的节点,并逐步更新距离数组。

该算法适用于无负权边的情况。

2. Bellman-Ford算法:通过迭代更新距离数组,每次都扫描所有的边,更新路径长度。

该算法适用于存在负权边的情况。

3. Floyd-Warshall算法:通过一个二维矩阵来存储任意两个节点之间的最短路径长度,通过尝试经过不同的中间节点来更新路径长度。

该算法适用于有向图或无向图,且适用于任意权重的情况。

4. A*算法:在Dijkstra算法的基础上引入启发函数,通过启发函数估计从起始点到目标节点的距离,并按照估计值进行优先级队列的排序。

该算法适用于图中存在目标节点的情况。

以上算法适用于不同的情况,具体选择哪个算法要根据问题的特点来决定。

单源点最短路径

单源点最短路径

单源点最短路径单源点最短路径是图论中的一种重要问题,用于寻找从一个特定节点到其他节点的最短路径。

在实际应用中,这个问题很常见,比如用于导航系统、通信网络、物流配送等领域。

下面将介绍单源点最短路径的定义、算法和应用。

需要明确单源点最短路径的定义。

在一个有向带权图中,每个边都有一个权重和方向。

单源点最短路径问题的目标是找到从给定的源节点s到所有其他节点的最短路径。

路径的长度由边的权重之和来衡量。

最短路径可能不唯一,但它们的长度必定是最小的。

接下来介绍两种经典的单源点最短路径算法:Dijkstra算法和Bellman-Ford算法。

Dijkstra算法是一种贪心算法,用于解决带权有向图的单源点最短路径问题。

它的基本思想是从源节点开始,逐层扩展,选择距离源节点最近的节点作为下一个中转节点。

通过动态维护一个距离数组,记录每个节点到源节点的当前最短路径长度,逐步更新和计算最短路径。

具体步骤如下:1.创建一个距离数组dist[],用于记录每个节点到源节点的当前最短路径长度。

初始化dist[]为无穷大,源节点的距离为0。

2.创建一个集合sptSet[],用于记录已经找到最短路径的节点。

初始化sptSet[]为空集合。

3.依次选择未加入sptSet[]的节点中距离源节点最近的节点u,并将u加入sptSet[]。

4.对于u的每个邻居节点v,如果经过u到v的路径长度dist[u]+weight(u,v)比dist[v]更小,则更新dist[v]。

5.重复步骤3和步骤4,直到最短路径全部找到。

Bellman-Ford算法是一种动态规划算法,用于解决带权有向图的单源点最短路径问题。

它通过迭代更新距离数组dist[],直到每个节点的最短路径长度不再改变,或者存在负权环。

具体步骤如下:1.创建一个距离数组dist[],用于记录每个节点到源节点的当前最短路径长度。

初始化dist[]为无穷大,源节点的距离为0。

2.重复以下步骤n-1次(其中n是图中节点的个数):-对于图中的每条边(u, v),如果dist[u] + weight(u, v)比dist[v]更小,则更新dist[v]。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单源最短路径计科一班李振华20120407111、问题描述给定带权有向图G=(V,E),其中每条边的权是非负实数。

另外,还给定V 中的一个顶点,称为源。

现在要计算从源到其他所有顶点的最短路长度。

这里路的长度是指路上各边权之和。

这个问题通常称为单源最短路径问题。

2、问题分析推导过程(最优子结构证明,最优值递归定义)1、贪心算法对于图G,如果所有Wij≥0的情形下,目前公认的最好的方法是由Dijkstra 于1959年提出来的。

已知如下图所示的单行线交通网,每弧旁的数字表示通过这条单行线所需要的费用,现在某人要从v1出发,通过这个交通网到v8去,求使总费用最小的旅行路线。

Dijkstra方法的基本思想是从vs出发,逐步地向外探寻最短路。

执行过程中,与每个点对应,记录下一个数(称为这个点的标号),它或者表示从vs 到该点的最短路的权(称为P标号)、或者是从vs到该点的最短路的权的上界(称为T标号),方法的每一步是去修改T标号,并且把某一个具T标号的改变为具P标号的点,从而使G中具P标号的顶点数多一个,这样至多经过n-1(n为图G的顶点数)步,就可以求出从vs到各点的最短路。

在叙述Dijkstra方法的具体步骤之前,说明一下这个方法的基本思想。

s=1。

因为所有Wij≥0,故有d(v1, v1)=0。

这时,v1是具P标号的点。

现在考察从v1发出的三条弧,(v1, v2), (v1, v3)和(v1, v4)。

(1)如果某人从v1出发沿(v1, v2)到达v2,这时需要d(v1, v1)+w12=6单位的费用;(2)如果他从v1出发沿(v1, v3)到达v3,这时需要d(v1, v1)+w13=3单位的费用;(3)若沿(v1, v4)到达v4,这时需要d(v1, v1)+w14=1单位的费用。

因为min{ d(v1, v1)+w12,d(v1, v1)+w13,d(v1, v1)+w14}= d(v1, v1)+w14=1,可以断言,他从v1到v4所需要的最小费用必定是1单位,即从v1到v4的最短路是(v1, v4),d(v1, v4)=1。

这是因为从v1到v4的任一条路P,如果不是(v1, v4),则必是先从v1沿(v1, v2)到达v2,或者沿(v1, v3)到达v3。

但如上所说,这时他已需要6单位或3单位的费用,不管他如何再从v2或从v3到达v4,所需要的总费用都不会比1小(因为所有wij≥0)。

因而推知d(v1, v4)=1,这样就可以使v4变成具P 标号的点。

(4)现在考察从v1及v4指向其余点的弧,由上已知,从v1出发,分别沿(v1, v2)、(v1, v3)到达v2, v3,需要的费用分别为6与3,而从v4出发沿(v4, v6)到达v6所需的费用是d(v1, v4)+w46=1+10=11单位。

因min{ d(v1, v1)+w12,d(v1, v1)+w13,d(v1, v4)+w46}= d(v1, v1)+w13=3。

基于同样的理由可以断言,从v1到v3的最短路是(v1, v3),d(v1, v3)=3。

这样又可以使点v3变成具P标号的点,如此重复这个过程,可以求出从v1到任一点的最短路。

在下述的Dijstra方法具体步骤中,用P,T分别表示某个点的P标号、T标号,si表示第i步时,具P标号点的集合。

为了在求出从vs到各点的距离的同时,也求出从Vs到各点的最短路,给每个点v以一个λ值,算法终止时λ(v)=m,表示在Vs 到v的最短路上,v的前一个点是Vm;如果λ(v)= ∞,表示图G中不含从Vs到v 的路;λ(Vs)=0。

Dijstra方法的具体步骤:{初始化}i=0S0={Vs},P(Vs)=0 λ(Vs)=0对每一个v<>Vs,令T(v)=+ ∞,λ(v)=+ ∞,k=s{开始}①如果Si=V,算法终止,这时,每个v∈Si,d(Vs,v)=P(v);否则转入②②考察每个使(Vk,vj)∈E且vj Si的点vj。

如果T(vj)>P(vk)+wkj,则把T(vj)修改为P(vk)+wkj,把λ(vj)修改为k。

③令如果,则把的标号变为P标号,令,k=ji,i=i+1,转①,否则终止,这时对每一个v∈Si,d(vs,v)=P(v),而对每一个。

在下图所给的有向图G中,每一边都有一个非负边权。

要求图G的从源顶点s到目标顶点t之间的最短路径。

2、分支限界法算法从图G的源顶点s和空优先队列开始。

结点s被扩展后,它的儿子结点被依次插入堆中。

此后,算法从堆中取出具有最小当前路长的结点作为当前扩展结点,并依次检查与当前扩展结点相邻的所有顶点。

如果从当前扩展结点i到顶点j有边可达,且从源出发,途经顶点i再到顶点j的所相应的路径的长度小于当前最优路径长度,则将该顶点作为活结点插入到活结点优先队列中。

这个结点的扩展过程一直继续到活结点优先队列为空时为止。

在算法扩展结点的过程中,一旦发现一个结点的下界不小于当前找到的最短路长,则算法剪去以该结点为根的子树。

在算法中,利用结点间的控制关系进行剪枝。

从源顶点s出发,2条不同路径到达图G的同一顶点。

由于两条路径的路长不同,因此可以将路长长的路径所对应的树中的结点为根的子树剪去。

3、计算求解过程、算法实现(源代码实现相关功能)1、贪心算法#include <iostream>#include <stdlib.h>using namespace std;#define MAX 1000000 //充当"无穷大"#define LEN sizeof(struct V_sub_S)#define N 5#define NULL 0int s; //输入的源点int D[N]; //记录最短路径int S[N]; //最短距离已确定的顶点集const int G[N][N] = { {0, 10, MAX, 30, 100},{MAX, 0, 50, MAX, MAX},{MAX, MAX, 0, MAX, 10},{MAX, MAX, 20, 0, 60},{MAX, MAX, MAX, MAX, 0} };typedef struct V_sub_S //V-S链表{int num;struct V_sub_S *next;};struct V_sub_S *create(){struct V_sub_S *head, *p1, *p2;int n = 0;head = NULL;p1 = (V_sub_S *)malloc(LEN);p1->num = s;head = p1;for(int i = 0; i < N+1; i ++){if(i != s){++ n;if(n == 1)head = p1;elsep2->next = p1;p2 = p1;p1 = (V_sub_S *)malloc(LEN);p1->num = i;p1->next = NULL;}}free(p1);return head;}struct V_sub_S *DelMin(V_sub_S *head, int i) //删除链表中值为i 的结点{V_sub_S *p1, *p2;p1 = head;while(i != p1->num && p1->next !=NULL){p2 = p1;p1 = p1->next;}p2->next = p1->next;return head;}void Dijkstra(V_sub_S *head, int s){struct V_sub_S *p;int min;S[0] = s;for(int i = 0; i < N; i ++){D[i] = G[s][i];}for(int i = 1; i < N; i ++){p = head->next;min = p->num;while(p->next != NULL){if(D[p->num] > D[(p->next)->num])min = (p->next)->num;p = p->next;}S[i] = min;head = DelMin(head, min);p = head->next;while(p != NULL){if(D[p->num] > D[min] + G[min][p->num]){D[p->num] = D[min] + G[min][p->num];}p = p->next;}}}void Print(struct V_sub_S *head){struct V_sub_S *p;p = head->next;while(p != NULL){if(D[p->num] != MAX){cout << "D[" << p->num << "]: " << D[p->num] << endl;p = p->next;}else{cout << "D[" << p->num << "]: " << "∞" << endl;p = p->next;}}}int main(){struct V_sub_S *head;cout << "输入源点s (0到4之间): ";cin >> s;head = create();Dijkstra(head, s);head = create();Print(head);system("pause");return 0;}2、分支限界法#include <iostream>#include <queue>using namespace std;#define MAX 9999#define N 60int n,dist[N],a[N][N];class HeapNode{public:int i,length;HeapNode() { }HeapNode(int ii,int l){i=ii;length=l;}bool operator<(const HeapNode& node)const{return length<node.length;}};void shorest(int v){priority_queue<HeapNode> heap;HeapNode enode(v,0);for(int i=1; i<=n; i++) dist[i]=MAX;dist[v]=0;while(1){for(int j=1; j<=n; j++)if(a[enode.i][j]<MAX && enode.length+a[enode.i][j]<dist[j]){dist[j]=enode.length+a[enode.i][j];HeapNode node(j,dist[j]);heap.push(node);}if(heap.empty()) break;else{enode=heap.top();heap.pop();}}}int main (){cin>>n;for(int i=1; i<=n; i++)for(int j=1; j<=n; j++){cin>>a[i][j];if(a[i][j]==-1) a[i][j]=MAX;}shorest(1);for(int i=2; i<n; i++) cout<<dist[i]<<" ";cout<<dist[n]<<endl;return 0;}3、运行结果(截图)4、计算复杂性分析(时间、空间)求单源、无负权的最短路。

相关文档
最新文档