图论单源最短路-出差

Posted 最差的研究生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论单源最短路-出差相关的知识,希望对你有一定的参考价值。

问题描述

A 国有 N 个城市, 编号为 1…N 。小明是编号为 1 的城市中一家公司的员 工, 今天突然接到了上级通知需要去编号为 N 的城市出差。

由于疫情原因, 很多直达的交通方式暂时关闭, 小明无法乘坐飞机直接从 城市 1 到达城市 N, 需要通过其他城市进行陆路交通中转。小明通过交通信息 网, 查询到了 M 条城市之间仍然还开通的路线信息以及每一条路线需要花费的 时间。

同样由于疫情原因, 小明到达一个城市后需要隔离观察一段时间才能离开 该城市前往其他城市。通过网络, 小明也查询到了各个城市的隔离信息。(由于 小明之前在城市 1 , 因此可以直接离开城市 1 , 不需要隔离)

由于上级要求, 小明希望能够尽快赶到城市 N , 因此他求助于你, 希望你 能帮他规划一条路线, 能够在最短时间内到达城市

图论-单源最短路-SPFA算法

有关概念:

  最短路问题:若在图中的每一条边都有对应的权值,求从一点到另一点之间权值和最小的路径

  SPFA算法的功能是求固定起点到图中其余各点的的最短路(单源最短路径)

  约定:图中不存在负权环,用邻接表存储有向图,di存放从起点到结点i的最短路,q为队列,保存待处理节点

思路:

  首先指定起点入队,取当前队头结点u,沿每一条与u相连的边向外扩展,对该边所指向的结点v松弛(比较当前dv与当前du加此边长,更新最短路值dv,以及最短路径prev)如果v不在队列中且更新了最短路值,v进队,直至队列中没有元素时终止

  较于Dijkstra,SPFA能处理带负权的边,但如果点进队的次数过多,时间效率就不如前者高

 1 #include<cstdio>
 2 #include<cstring>
 3 #define MAXN
 4 #define MAXM
 5 #define INF 214748364
 6 int n,m,cnt,d[MAXN],heads[MAXN],q[MAXN],pre[MAXN];
 7 int head,tail;//队头、队尾指针
 8 bool viss[MAXN];//结点i是否在队列中
 9 struct node
10 {
11     int u,v;
12     int next;
13     int val;
14 }edge[MAXM];
15 void add(int x,int y,int z)
16 {
17     edge[++cnt].u=x;
18     edge[cnt].v=y;
19     edge[cnt].next=heads[x];
20     edge[cnt].val=z;
21     heads[x]=cnt;
22 }
23 void SPFA()
24 {
25     head=1;tail=2;
26     q[1]=1;
27     viss[1]=1;//默认1为起点
28     while(head<tail)
29     {
30         for(int i=heads[q[head]];i!=0;i=edge[i].next)
31         {
32             if(d[q[head]]+edge[i].val<d[edge[i].v])
33             {
34                 d[edge[i].v]=d[q[head]]+edge[i].val;//松弛
35                 pre[edge[i].v]=i;//记录最短路径,pre存储边的序号
36                 if(!viss[edge[i].v])//如果v不在队列中,入队
37                 {
38                     q[tail++]=edge[i].v;
39                     viss[edge[i].v]=true;
40                 }
41             }
42         }
43         viss[q[head]]=false;
44         head++;//队头出队
45     }
46 }
47 void print(int x)
48 {
49     if(edge[x].u==1)
50     {
51         printf("%d %d ",1,edge[x].v);
52         return ;
53     }
54     print(pre[edge[x].u]);
55     printf("%d ",edge[x].v);
56 }
57 int main()
58 {
59     scanf("%d%d",&n,&m);
60     memset(heads,0,sizeof(heads));
61     for(int i=2;i<=n;i++)d[i]=INF;
62     int x,y,z;
63     for(int i=1;i<=m;i++)
64     {
65         scanf("%d%d%d",&x,&y,&z);
66         add(x,y,z);
67         add(y,x,z);//默认输入双向边,所以存储两条方向相反的边
68     }
69     SPFA();
70     printf("%d\n",d[n]);
71     x=pre[n];
72     print(x);//输出路径
73     return 0;
74 }

*参考:

http://baike.baidu.com/link?url=FxZ5Ces0YdAHMPmVyJG7f_wJ9-8c6EHreyuDEfHpXsldfk-rfj7ZjtSETKX5Jp14WW28sutbf5zcnLSBcmKzM9zaUVD1Sn9WCwsidDVUhPnSX__1ukG38VjR5g5-5NvK_fjovt-kZIJ1bC4HK1MaBa

以上是关于图论单源最短路-出差的主要内容,如果未能解决你的问题,请参考以下文章

小航的算法日记图论

简单的图论问题之单源最短路dijkstra算法

算法笔记:图论中的单源最短路径算法——Bellman-Ford 算法

洛谷 p3371模板-单源最短路径(图论)

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

图论 最短路总结