L2-001. 紧急救援 (Dijkstra算法打印路径)

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出格式:

第一行输出不同的最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出首尾不能有多余空格。

输入样例:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

输出样例:

2 60
0 1 3
  1 #include<stdio.h>
  2 #include<math.h>
  3 #include<stdlib.h>
  4
  5 #define MAX 502
  6 #define INFI 9999999
  7
  8 int G[MAX][MAX],nv,ne,c1,c2; //图,结点数,边数,起点,终点
  9 int know[MAX];              //访问标记
 10 int distance[MAX];          //距离
 11 int num[MAX];               //最短路径条数
 12 int weight[MAX];           //每个点的权值
 13 int w[MAX];                //最短路径上的点权值总和
 14 int pre[MAX];              //存放每个结点前一个结点
 15 void printPath( int v);
 16 void CreateGraph();
 17 void Dijkstra( );
 18 int main()
 19 {
 20     int i;
 21     scanf("%d%d%d%d",&nv,&ne,&c1,&c2);
 22     for( i=0; i<nv; i++)
 23         scanf("%d",&weight[i]);
 24     CreateGraph();
 25     Dijkstra();
 26     printf("%d %d\n",num[c2],w[c2]);
 27     printPath(c2);
 28     return 0;
 29 }
 30
 31 void CreateGraph()
 32 {
 33     int i,j;
 34     int v1,v2;
 35     int dn;
 36     for( i=0; i<nv; i++)
 37         for( j=0; j<nv; j++)
 38             G[i][j]=INFI;
 39     for( i=0; i<ne; i++)
 40     {
 41         scanf("%d%d%d",&v1,&v2,&dn);
 42         G[v1][v2]=G[v2][v1]=dn;  //无向图
 43     }
 44 }
 45 void Dijkstra( )
 46 {
 47     int i,j,k;
 48     int min;
 49     for( i=0; i<nv; i++)
 50     {
 51         know[i]=0;
 52         distance[i]=G[c1][i];  //更新起点到所有顶点的距离
 53     }
 54     distance[c1]=0;           //起点到起点的距离为0
 55     w[c1]=weight[c1];
 56     num[c1]=1;
 57     for( i=1; i<nv; i++)
 58     {
 59         k=-1;
 60         min = INFI;
 61         for( j=0; j<nv; j++)
 62         {
 63             if( !know[j] && distance[j]<min)
 64             {
 65                 k=j;
 66                 min = distance[j];
 67             }
 68         }
 69         if( k==-1) break;
 70         know[k]=1;  //寻找到最短的距离,标记该点
 71         for( j=0; j<nv; j++)
 72         {
 73             if( !know[j] && min+G[k][j]<distance[j])  //更新距离
 74             {
 75                 distance[j] = min+G[k][j];
 76                 num[j] = num[k];
 77                 w[j] = w[k] + weight[j];
 78                 pre[j]=k;
 79             }
 80             else if( !know[j] && min+G[k][j]==distance[j])
 81             {
 82                 num[j]=num[j]+num[k];
 83                 if( w[k]+weight[j]>w[j])
 84                 {
 85                     w[j]=w[k]+weight[j];
 86                     pre[j]=k;
 87                 }
 88             }
 89         }
 90     }
 91 }
 92
 93 void printPath( int v)  //递归打印路径
 94 {
 95     if( v==c1){
 96         printf("%d",v);
 97         return;
 98     }
 99     printPath( pre[v]);
100     printf(" %d",v);
101 }

原文地址:https://www.cnblogs.com/yuxiaoba/p/8538192.html

时间: 2024-07-31 06:14:34

L2-001. 紧急救援 (Dijkstra算法打印路径)的相关文章

Floyd 算法 打印路径模板

#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <cmath> #include <cstring> using namespace std; #define INF 0xfffffff #define maxn 40

POJ 3255 Roadblocks (次短路径 + Dijkstra算法)

Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7982   Accepted: 2921 Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too q

vijos1635 SPFA和FLOYD算法如何打印路径

之前打的spfa或是floyd都只是用来求最短路,对于如何打印路径问题一点都没有概念 可能也是因为对于原理没有很理解的缘故? 总之,之后赶紧看了一下,现在总算是明白了.....MARK一下自己的理解 早晨碰到了一题挺裸的最短路问题:vijos1635 1.首先说说spfa的方法: 其实自己之前打的最多的spfa是在网格上的那种,也就是二维的 一维的需要邻接表+queue 以及对于queue的操作,自己也是醉了 这里贴一个模板(不含打印路径): #include<cstdio> #include

Dijkstra算法(带路径模板)

个人心得:Dijkstra算法是贪心思想的一种延伸,注意路径pre,pre数组表示此时最短路径中的前一个顶点.每次更新到目的点时更新: 从源点出发,更新路径,然后找出此时最短的点,然后以这个点为头,看能否缩减路程, #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> usi

最短路问题 Dijkstra算法- 路径还原

1 // 路径还原 2 // 求最短路,并输出最短路径 3 // 在单源最短路问题中我们很容易想到,既然有许多条最短路径,那将之都存储下来即可 4 // 但再想一下,我们是否要把所有的最短路径都求出来呢? 5 // 实际上不需要,这里我们用一个数组来记录最短路径,之后的最短路径都是在之前最短路径上的延申 6 // 所以只需要一个数组,存储前一个节点即可 7 8 // 这里我们用邻接表和优先级队列来实现复杂度为o( E*log(N) )的Dijkstra算法 9 10 #include <cstd

山东省第七届ACM竞赛 C题 Proxy (Dijkstra算法,单源路径最短问题)

题意:给定0-n+1个点,和m条边,让你找到一条从0到n+1的最短路,输出与0相连的结点... 析:很明显么,是Dijkstra算法,不过特殊的是要输出与0相连的边,所以我们倒着搜,也是从n+1找到0, 那么不就能找到与0相连的边么,注意判断相等值的时候.当时写错了好多次,就是没有考虑好边界. 代码如下: #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #

Dijkstra 算法

最短路径算法的基础知识,参见 http://blog.csdn.net/pacosonswjtu/article/details/49894021 Dijkstra算法 涉及到的 优先队列的操作实现(该优先队列的数据类型不是 int , 而是 Distance),详情参见http://blog.csdn.net/pacosonswjtu/article/details/49923389 [1]Dijkstra 算法相关 1.1)贪婪算法一般分阶段去求解一个问题, 在每个阶段它都把当前出现的当做是

Dijkstra算法 --- 单源最短路

Dijkstra算法适用于边权值为正的情况,可用于计算正权图上的单元最短路. 其伪代码如下: 设d[v0] = 0, 其他d[i] = INF 循环n次{ 在所有未标号的结点中,选取d值最小的结点x 给结点x加上永久标号 对于从x出发的所有边,执行松弛操作. } //松弛操作的伪代码如下: RELAX(u,v,w) if(u.d + w(u,v) < v.d){ v.d = w.d + w(u,v); pre[v] = u; } Dijkstra算法代码: /* Dijkstra 单源最短路算法

算法导论-第24章 Dijkstra算法

Dikstra算法解决的是有向图上单源最短路径问题(无向图可以看成有相反的两条有向边),且要求边的权重都是非负值. 算法导论用了很多引理,性质来证明Dijstra算法的正确性,这里不说了,也表达不明白,只说我理解的过程. 有一个图G( V,E) ,选定一个源点s,维护一个集合Q=V-s,  Q中点有一个d值表示此时从s到该点的已知距离,s.d=0 :初始化都为正无穷,表明不可达.然后对s点所连接的点(设为点集M)进行松弛操作,就是设点m属于M, m.d > s.d+ w(s,m) 则更新 m.d