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

合集下载

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

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

¾ 规律:当按长度增序生成从源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]。

最短路算法总结---单源最短路径(SSSP)

最短路算法总结---单源最短路径(SSSP)

最短路算法总结---单源最短路径(SSSP)众所周知,最短路算法在⽐赛中占有相当部分的分值在⼤多数情况下,甚⾄使⽤并⾮最佳的算法也可以的得到相当⼤部分的分数。

以下选⾃书中核⼼内容,是竞赛⽣要熟练掌握且清晰理解的⼏种最基本算法。

(全部化为有向图做,双向边就化为两条单向边,恩,就这样操作)以下所有讨论不考虑环,全部INF处理,请悉知。

⼀.Dijkstra算法(贪⼼)(O(n^2))(效率⼀般,但相当可做)(边权⾮负,否则。

qwq)1.dist[1]=0 ,其余 dist = INF->2.找出⼀个未标记,dist[x]最⼩的节点x,标记x。

->3.扫描节点x的所有出边(x,y,z),if (dist[y]>dist[x]+z ) dist[y]=dist[x]+z (这是这个最基本的算法的核⼼语句,具体可想象三⾓形三边关系)。

(注意这⾥边权为负数的话,那么我们2中最先选择出的起点就不⼀定最⼩了,那万⼀以后跑出来个负边,全局都会受影响,那咱还贪个啥⼼,还跑个啥Dijkstra)4.重复2-3直到全部点都被标记(233要是所有点⾛的线路都试过了,没有答案你来打我啊)⼆.Bellman-Ford算法(O(nm))(我不咋⽤,但这个是SPFA的原型)->1.扫描所有边(x,y,z),if (dist[y]>dist[x]+z)dist[y]=dist[x]+z (我没看错吧?我把上⽂抄了下来?没错,⼏种算法的基本套路是⼀样的)(但要注意,这⾥不同的是这⾥Bell-ford的2并⾮像Dijkstra那样要求对所有点扫描,⽽仅仅是某⼀部分。

)(为神魔呢?这是样做有道理的。

证明:若⼀张有向图的⼀条边满⾜三⾓形不等式,即dist[y]<=dist[x]+z,那么所有这样的边连起来的⼀条路肯定最短啦,⼲嘛还要把所有边都跑⼀边呢,这样就剪掉很多不必要去扫的边)2.重复,直到1那家伙扫完(即基于三⾓不等式的关系下不再发⽣任何更新)。

迪杰斯特拉算法求单源最短路径

迪杰斯特拉算法求单源最短路径

迪杰斯特拉算法是一种用于求解单源最短路径的经典算法,它被广泛应用于网络路由、电信领域以及各种其他实际问题中。

本文将从以下几个方面详细介绍迪杰斯特拉算法的原理、实现以及应用,以帮助读者深入理解并掌握该算法。

一、迪杰斯特拉算法的原理迪杰斯特拉算法的核心思想是通过逐步确定从起点到其他顶点的最短路径来求解单源最短路径问题。

其具体原理包括以下几个步骤:1. 初始化:将起点到所有其他顶点的距离初始化为无穷大,起点到自身的距离为0,并建立一个空的集合S来存放已确定最短路径的顶点。

2. 选择最近顶点:从未确定最短路径的顶点中选择距离起点最近的顶点u加入集合S。

3. 更新距离:对于顶点集合V-S中的每个顶点v,如果通过顶点u可以找到一条比当前最短路径更短的路径,则更新起点到顶点v的距离。

4. 重复步骤2和步骤3,直到集合S包含所有顶点。

通过上述步骤,迪杰斯特拉算法可以求解出起点到图中所有其他顶点的最短路径。

二、迪杰斯特拉算法的实现迪杰斯特拉算法可以通过多种数据结构来实现,其中最常见的是使用优先队列来存储未确定最短路径的顶点,并通过松弛操作来更新顶点的距离。

下面将介绍一种基于优先队列的迪杰斯特拉算法实现方法:1. 初始化距离数组dist[],其中dist[i]表示起点到顶点i的最短距离,将所有顶点初始化为无穷大,起点初始化为0。

2. 将起点加入优先队列,并将其距离更新为0。

3. 循环执行以下步骤直到优先队列为空:(1)从优先队列中取出距离起点最近的顶点u。

(2)遍历顶点u的所有邻接顶点v,对于每个邻接顶点v,如果通过顶点u可以找到一条更短的路径,则更新顶点v的距离,并将其加入优先队列。

通过上述实现,我们可以得到起点到所有其他顶点的最短路径。

三、迪杰斯特拉算法的应用迪杰斯特拉算法在实际应用中有着广泛的应用场景,其中最典型的应用包括网络路由、电信领域以及地图路径规划等。

1. 网络路由:在计算机网络中,迪杰斯特拉算法被用于寻找最短路径,以确保数据包以最短的路径到达目的地,提高网络传输效率。

单源最短路径算法

单源最短路径算法

单源最短路径算法常见的单源最短路径算法有迪杰斯特拉算法(Dijkstra's algorithm)和贝尔曼-福特算法(Bellman-Ford algorithm)。

本文将详细介绍这两种算法的实现原理和特点。

1.迪杰斯特拉算法:迪杰斯特拉算法是一种用于求解带权重图的单源最短路径的算法。

它的基本思想是,维护一个集合S,初始时包含源节点,不断地向集合S中加入离源节点最近的节点,直到所有节点都加入了集合S。

在每次加入节点的过程中,更新源节点到集合S中每个节点的最短距离。

迪杰斯特拉算法的步骤如下:1)初始化源节点的最短距离为0,其他节点的最短距离为无穷大。

2)将源节点加入集合S。

3)对于源节点的每个邻居节点,更新从源节点到邻居节点的最短距离。

如果更新后的距离更短,更新邻居节点的最短距离。

4)从集合S中选择一个离源节点最近的节点加入集合S,并重复步骤35)重复步骤4,直到所有节点都加入了集合S。

迪杰斯特拉算法的时间复杂度为O(V^2),其中V是节点的数量。

在稠密图中,即边的数量接近节点的数量平方时,迪杰斯特拉算法表现较好。

2.贝尔曼-福特算法:贝尔曼-福特算法是一种用于求解带有负权重边的单源最短路径的算法。

与迪杰斯特拉算法不同的是,贝尔曼-福特算法可以处理负权重边。

贝尔曼-福特算法的基本思想是,通过对边进行松弛操作,不断地更新节点的最短距离,直到找到所有节点的最短距离。

算法的步骤如下:1)初始化源节点的最短距离为0,其他节点的最短距离为无穷大。

2)对于边的数量-1次迭代,做以下操作:a)遍历所有边,对每条边(u,v),如果源节点u的最短距离加上边的权重w小于目标节点v的最短距离,则更新目标节点v的最短距离。

3)再进行一次遍历,如果仍然存在可以松弛的边,则说明存在负权重环。

贝尔曼-福特算法的时间复杂度为O(V*E),其中V是节点的数量,E 是边的数量。

相较于迪杰斯特拉算法,贝尔曼-福特算法的时间复杂度更高,但是它可以处理带有负权重边的图。

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

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

求解单源最短路径问题的算法单源最短路径问题是指从图中的一个顶点到其他所有顶点的最短路径的问题。

下面将详细介绍两种经典的求解该问题的算法:Dijkstra算法和Bellman-Ford 算法。

1. Dijkstra算法:- 初始化:将源顶点的距离初始化为0,其他顶点的距离初始化为无穷大。

创建一个集合S,记录已经确定最短路径的顶点。

- 重复以下步骤,直到集合S包含所有顶点:- 从未确定最短路径的顶点中选择距离源顶点最近的顶点u,并将其加入集合S。

- 对于与u相邻的顶点v,更新其距离为:min(distance[v], distance[u] + weight(u, v)),其中weight(u, v)表示边(u, v)的权值。

- 最终得到源顶点到图中所有其他顶点的最短路径。

2. Bellman-Ford算法:- 初始化:将源顶点的距离初始化为0,其他顶点的距离初始化为无穷大。

- 重复以下步骤,执行V-1次(V为顶点数):- 遍历图中的所有边,对于每条边(u, v),更新顶点v的距离为:min(distance[v], distance[u] + weight(u, v))。

- 检查是否存在负权回路:再次遍历所有边,如果对于边(u, v),发现distance[v] > distance[u] + weight(u, v),则说明存在从源顶点可达的负权回路,无法确定最短路径;否则,最短路径已经确定。

Dijkstra算法适用于无负权边且图稠密的情况,时间复杂度为O(V^2),也可以通过最小堆优化(时间复杂度为O((V+E)logV))。

Bellman-Ford算法适用于有负权边或存在负权回路的情况,时间复杂度为O(VE)。

需要注意的是,以上算法都是解决单源最短路径问题的经典算法,也可以使用其他如SPFA、Floyd-Warshall等算法求解,选择合适的算法应根据具体问题的要求和图的特性进行评估和选择。

单源最短路径算法(Dijkstra算法)

单源最短路径算法(Dijkstra算法)

设图G=(V,E)是一个有向图,它的每一条边(U,V)都有一个非负权W(U,V),在G中指定一个结点V0,要求从V0到G的每一个结点Vj的最短路径找出来(或指出不存在)。

由于源结点V0是给定的,所谓称为单源最短路径。

【Dijkstra算法思想】把所有结点分为两组。

第一组:包含已确定最短路径的结点。

第二组:包含尚未确定最短路径的结点。

按最短路径长度递增的顺序把第二组的结点加到第一组中去,直到V0可达的所有结点都包含于第一组中。

在这个过程中,总保持从V0到第一组各结点的最短路径长度都不大于从V0到第二组任何结点的路径长度。

【单源最短路径算法实例】现有一张县城的城镇地图,图中的顶点为城镇,无向边代表两个城镇间的连通关系,边上的权为公路造价,县城所在的城镇为v0。

由于该县经济比较落后,因此公路建设只能从县城开始规划。

规划的要求是所有可到达县城的城镇必须建设一条通往县城的汽车线路,该线路的工程总造价必须最少。

【输入】第一行一个整数v,代表城镇数,县城编号为1。

第二行是一个整数e,表示有向边数。

以下e行,每行为两个城镇编号和它们之间的公路造价。

【输出】 v-1行,每行为两个城市的序号,表明这两个城市间建一条公路。

【输入样例】6101 2 101 5 191 6 212 3 52 4 62 6 113 4 64 5 184 6 145 6 33 【输出样例】原图从第1点出发的最短路径1 22 32 41 51 6program dijkstra_example;constvmax=100;typepath=record {此记录类型用于记录每一个结点与v0的距离和其父结点} length:integer;pre:0..vmax;end;varw:array[1..vmax,1..vmax] of integer;dist:array[1..vmax] of path;v,e,u,i,j,x,y:integer;procedure init;beginassign(input,'dijkstra.in');reset(input);assign(output,'dijkstra.out');rewrite(output);readln(v);readln(e);for i:=1 to v dofor j:=1 to v doif i<>jthen w[i,j]:=maxint{maxint只是一个较大的数的意思,实际应用于应该根据题目中给出的取值范围赋予一个充else w[i,j]:=0;for i:=1 to e dobeginread(x,y);readln(w[x,y]);w[y,x]:=w[x,y];end;end;procedure dijkstra(v0:integer);varmin:integer;beginw[v0,v0]:=1; {v0首先进入第一组}for i:=1 to v dobegindist[i].length:=w[v0,i]; {计算每个结点的距离值}if dist[i].length<>maxintthen dist[i].pre:=v0 {如和v0直接有路,则置前驱结点为v0} else dist[i].pre:=0;end;repeatmin:=maxint;u:=0;for i:=1 to v do {找最短距离}if (w[i,i]=0) and (dist[i].length<min)then beginu:=i;min:=dist[i].length;end;then beginw[u,u]:=1;for i:=1 to v do {重新计算其他结点的距离值}if (w[i,i]=0) and (dist[i].length>dist[u].length+w[u,i]) then begindist[i].length:=dist[u].length+w[u,i];dist[i].pre:=u;end;end;until u=0;end;begininit;v0:=1;dijkstra(v0);for i:=1 to v dobeginif (i<>v0) and (dist[i].length<>maxint)then write(dist[i].pre,' ',i);end;close(input);close(output);end.。

贪心算法和分支限界法解决单源最短路径

贪心算法和分支限界法解决单源最短路径

贪⼼算法和分⽀限界法解决单源最短路径单源最短路径计科1班朱润华 2012040732⽅法1:贪⼼算法⼀、贪⼼算法解决单源最短路径问题描述:单源最短路径描述:给定带权有向图G=(V,E),其中每条边的权是⾮负实数。

另外,还给定V中的⼀个顶点,称之为源(origin)。

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

这⾥的路径长度指的是到达路径各边权值之和。

Dijkstra算法是解决单源最短路径问题的贪⼼算法。

Dijkstra算法的基本思想是:设置顶点集合S并不断地做贪⼼选择来扩充集合。

⼀个顶点属于集合S当且仅当从源点到该顶点的最短路径长度已知。

贪⼼扩充就是不断在集合S中添加新的元素(顶点)。

初始时,集合S中仅含有源(origin)⼀个元素。

设curr是G的某个顶点,把从源到curr 且中间只经过集合S中顶点的路称之为从源到顶点curr的特殊路径,并且使⽤数组distance记录当前每个顶点所对应的最短路径的长度。

Dijkstra算法每次从图G中的(V-S)的集合中选取具有最短路径的顶点curr,并将curr加⼊到集合S中,同时对数组distance 进⾏必要的修改。

⼀旦S包含了所有的V中元素,distance数组就记录了从源(origin)到其他顶点的最短路径长度。

⼆、贪⼼算法思想步骤:Dijkstra算法可描述如下,其中输⼊带权有向图是G=(V,E),V={1,2,…,n},顶点v 是源。

c是⼀个⼆维数组,c[i][j]表⽰边(i,j)的权。

当(i,j)不属于E时,c[i][j]是⼀个⼤数。

dist[i]表⽰当前从源到顶点i的最短特殊路径长度。

在Dijkstra算法中做贪⼼选择时,实际上是考虑当S添加u之后,可能出现⼀条到顶点的新的特殊路,如果这条新特殊路是先经过⽼的S到达顶点u,然后从u经过⼀条边直接到达顶点i,则这种路的最短长度是dist[u]+c[u][i]。

如果dist[u]+c[u][i]1、⽤带权的邻接矩阵c来表⽰带权有向图, c[i][j]表⽰弧上的权值。

1单源最短路径问题

1单源最短路径问题

dist[j]=E.length+c[E.i][j]; prev[j]=E.i; // 加入活结点优先队列 MinHeapNode<Type> N; N.i=j; N.length=dist[j]; H.Insert(N);} try {H.DeleteMin(E);} // 取下一扩展结点 catch (OutOfBounds) {break;} // 优先队列空 }}
顶点i和j间有边,且此路 径长小于原先从源点到j 的路径长
11
单源最短路径
总结: 分支限界法,通过目标函数和约 束条件减少无效操作,尽早发现剪枝 点。适用于解决满足约束条件的解中 找出是目标函数值达到最大或最小的 解。 所以单源最短路径很适合用分支限界 法解决~~
12134Fra bibliotekh6
8
单源最短路径
a
s b 3 c 4 f 5 k m 6 l 10 12 h 6
当前最短路程为4,将其扩展 即走aeq,aek; 计算最短路程为5,注意:当 前结点不小于已找到的最短路 程,剪枝:不再扩展 继续,最短路程为5, 将其扩展,即bgm,bgl; 计算最短路径为5.满足剪枝条 件,剪枝。
1
2
单源最短路径
给定带权有向图G =(V,E),其中每条 边的权是非负实数。另外,还给定V中的 一个顶点,称为源。现在要计算从源到所 有其它各顶点的最短路长度。这里路的长 度是指路上各边权之和。这个问题通常称 为单源最短路径问题。
3
从s点出发到t点,如何找到最短路径
d7 a2 b3 e2 f9 g2 c4 h2 q i5 j3 k3 l5 m1
下图是用优先队列式分支限界法解有向图G的 单源最短路径问题产生的解空间树的剪枝情况。

解最短路径问题的两种方法及其应用

解最短路径问题的两种方法及其应用

解最短路径问题的两种方法及其应用
最短路径问题是指在一张带权图中找到两个节点之间最短的路径。

最短路径问题是许多计算机科学和应用领域中的一个基本问题。

以下是解决这个问题的两种方法:
1. Dijkstra算法:Dijkstra算法是解决最短路径问题的一种
基本算法,它是基于贪心思想的。

该算法首先确定起始点到其他节
点的距离(记为d),然后不断扩大已确定最短距离的节点集,直
到覆盖所有节点。

Dijkstra算法适用于单源最短路径,即从一个节
点到所有其他节点的最短路径。

2. Floyd算法:Floyd算法也是一种经典的解决最短路径问题
的算法,它是一个动态规划算法。

该算法利用动态规划的思想,通
过比较任意两个节点之间经过第三点(中转点)的路径长度,更新
路径长度。

Floyd算法适用于多源最短路径,即从任意两个节点之
间的最短路径。

这两种算法可广泛应用于各种计算机科学和应用领域,如网页
排名算法、图像处理、计算机网络等。

在实际应用中,我们需要根
据实际问题的特点,选择最适合的算法。

单源最短路径算法

单源最短路径算法

单源最短路径算法这篇文章将介绍两种常用的单源最短路径算法,Dijkstra算法和Bellman-Ford算法,它们分别使用了贪心法和动态规划的思想来解决该问题。

一、Dijkstra算法:Dijkstra算法是一种贪心法的算法,以其发明者荷兰计算机科学家Edsger W. Dijkstra的名字命名。

它的基本思想是通过逐步扩展已知最短路径集合,直到找到从起始节点到目标节点的最短路径为止。

算法步骤如下:1.初始化距离数组,将起始节点到所有其他节点的距离初始化为无限大。

2.将起始节点的距离设置为0。

3.对于与起始节点直接相连的节点,更新距离数组的值为起始节点到这些节点的距离。

4.选择距离数组中值最小且未访问过的节点作为下一个当前节点。

5.更新从起始节点到当前节点经过未访问过的节点的距离,并更新距离数组中的值。

6.重复步骤4和5,直到所有节点都被访问过或者无法再找到更短的路径。

Dijkstra算法的时间复杂度为O(V^2),其中V为图中节点的数量。

使用优先队列或堆数据结构可以将时间复杂度降低到O((V+E)logV)。

二、Bellman-Ford算法:Bellman-Ford算法是一种动态规划的算法,它以其发明者Richard Bellman和Leslie Ford的名字命名。

与Dijkstra算法不同的是,Bellman-Ford算法可以处理含有负权边的图。

算法步骤如下:1.初始化距离数组,将起始节点到所有其他节点的距离初始化为无限大。

2.将起始节点的距离设置为0。

3.对于每条边,更新距离数组的值为起始节点到目标节点的距离。

4.重复步骤3,直到所有节点的距离不再改变。

5.检查是否存在负权回路,如果存在,说明不存在最短路径。

Bellman-Ford算法的时间复杂度为O(VE),其中V为图中节点的数量,E为图中边的数量。

总结:Dijkstra算法和Bellman-Ford算法是解决单源最短路径问题的两种常用算法。

最短路径问题和解法

最短路径问题和解法

最短路径问题和解法最短路径问题是计算一个图中从一个源点到目标点的最短路径问题,是图论中的重要问题之一。

该问题的解法可以划分为两种:单源最短路径问题和全源最短路径问题。

一、单源最短路径问题单源最短路径问题是指从一个源点出发,计算该源点到其他所有点的最短路径的问题。

解法有两种:Dijkstra算法和Bellman-Ford算法。

1. Dijkstra算法Dijkstra算法是一种贪心算法,每次将到源点距离最短的点加入已求出最短路径的点集。

虽然Dijkstra算法只适用于边权值均为正的带权有向图或者无向图,但是它的时间复杂度相比Bellman-Ford算法更优秀,为O(n^2)。

2. Bellman-Ford算法Bellman-Ford算法是一种较为通用的算法,不需要图的属性满足任何特殊要求,但是时间复杂度为O(n^3),不适用于大规模的图。

算法原理是进行n次松弛操作,查找从源点到其他点的最短路径,其中进行松弛的过程是比较消耗时间的。

二、全源最短路径问题全源最短路径问题是指求解所有点之间的最短路径问题。

解法有两种:Floyd算法和Johnson算法。

3. Floyd算法Floyd算法是一种动态规划算法,算法将所有点对之间的最短路径逐步推进,通过枚举中间点,得到更加精细的状态转移方程和最短路径。

时间复杂度为O(n^3),因此带来的计算负担较大。

4. Johnson算法Johnson算法目前是解决稠密图最短路径问题的最好算法之一。

Johnson算法先通过引入虚拟点,将原图转化为一个没有负权边的新图,再对新图使用Dijkstra算法进行求解。

该算法的时间复杂度为O(mnlogn),其中m为边的条数,n为点的个数。

综上所述,最短路径问题是图论中的重要问题之一。

对于单源最短路径问题,Dijkstra算法和Bellman-Ford算法是常用的解法;全源最短路径问题,Floyd算法和Johnson算法是较为常用的解法。

单源最短路径问题算法

单源最短路径问题算法

单源最短路径问题算法一、概述单源最短路径问题是指在一个有向带权图中,给定一个起点,求出该起点到所有其他点的最短路径。

这个问题在实际应用中非常常见,例如地图导航、网络路由等。

二、算法分类1. Dijkstra算法Dijkstra算法是解决单源最短路径问题的一种经典算法。

该算法使用了贪心策略,每次选取当前距离起点最近的未访问节点作为下一个节点,并更新其周围节点的距离值。

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

2. Bellman-Ford算法Bellman-Ford算法是另一种解决单源最短路径问题的经典算法。

该算法使用动态规划的思想,通过对所有边进行松弛操作来更新每个节点的距离值。

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

3. SPFA算法SPFA(Shortest Path Faster Algorithm)算法是一种基于Bellman-Ford思想和队列优化技巧的改进型算法。

SPFA在处理稀疏图时比Bellman-Ford更快,并且可以处理存在负权边但不存在负权环的情况。

4. Floyd-Warshall算法Floyd-Warshall算法是解决全源最短路径问题的一种经典算法。

该算法使用动态规划的思想,通过对每对节点之间进行松弛操作来更新它们之间的最短路径。

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

三、算法实现1. Dijkstra算法Dijkstra算法可以使用堆优化来提高效率。

以下是使用堆优化的Dijkstra算法实现:```pythonimport heapqdef dijkstra(graph, start):# 初始化距离字典和堆dist = {node: float('inf') for node in graph}dist[start] = 0heap = [(0, start)]while heap:# 取出距离起点最近的节点(distance, node) = heapq.heappop(heap)# 更新周围节点的距离值for neighbor, weight in graph[node].items():new_distance = dist[node] + weightif new_distance < dist[neighbor]:dist[neighbor] = new_distanceheapq.heappush(heap, (new_distance, neighbor))return dist```2. Bellman-Ford算法Bellman-Ford算法需要进行多次松弛操作来更新每个节点的距离值,以下是Bellman-Ford算法实现:```pythondef bellman_ford(graph, start):# 初始化距离字典dist = {node: float('inf') for node in graph}dist[start] = 0# 进行n-1轮松弛操作for i in range(len(graph) - 1):for node in graph:for neighbor, weight in graph[node].items(): new_distance = dist[node] + weightif new_distance < dist[neighbor]:dist[neighbor] = new_distance# 检查是否存在负权环for node in graph:for neighbor, weight in graph[node].items():if dist[node] + weight < dist[neighbor]:raise ValueError('Negative cycle detected')return dist```3. SPFA算法SPFA算法使用队列来存储需要更新的节点,并使用一个标记数组来记录每个节点是否在队列中。

  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、计算复杂性分析(时间、空间)求单源、无负权的最短路。

相关文档
最新文档