目录

​1,题目描述​

​题意解析:​

​输入:​

​输出:​

​2,思路​

​Dijkstra算法​

​注意点:​

​3,代码​


1,题目描述

PAT_甲级_1003 Emergency (25分) (C++)_甲级

Sample Input:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

 

Sample Output:

2 4

题意解析:

目的城市发生事故,需要从所在城市赶往目的城市,寻找最短路径,并且在路中联系尽可能多的救护队前往救护。

题目保证任意两城市间至少有一条路

输入:

第一行:城市的数目N,路的数目M,所在城市编号C1,目的城市编号C2

第二行:N个城市对应各自救护队的数目

剩下M行:连接的两个城市编号C1、C2,及路的长度

输出:

从C1到C2不同最短路径的数目;

最短路径中可以集合的救护队的最多数目;

 

2,思路

意思很清楚,就是利用dijkstra算法;想再复习一下算法的同学可以戳这里​​@ heroacool 【数据结构--Dijkstra算法最清楚的讲解】​

这里再简单描述一下:

Dijkstra算法

此算法用于解决图中从一点到其他所有顶点的最短路径问题;

  1. 从一个初始顶点出发,遍历邻近的所有顶点,取出最近的顶点放入visited中;
  2. 遍历visited数组中顶点邻近的所有顶点,找到最近的顶点放入visited中;
  3. 重复以上步骤2,直至所有顶点均遍历一遍;

注意点:

  1. 题目的限制,城市数量小于等于500;
  2. 注意记录最短路径的数目(小于当前最短路径时,更新;等于当前最短路径时,累加)和到达节点累加的点权值(小于当前最短路径时,更新;等于当前最短路径时,取最大值);
  3. 由于每个点的最短路径的数目和累加的点权值都需要记录,故均为他们开辟数组;

 

3,代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
using namespace std;

int main(){
//#ifdef ONLINE_JUDGE
//#else
// freopen("1.txt", "r", stdin);
//#endif

int n, m, c1, c2; //n:城市数 m:路数 c1:所在城市 c2:目的城市
int graph[500][500]; //邻接矩阵 记录边的权值
int weight[500]; //每个城市的救护队数目
int weight_[500]; //到达每个点累计的最多救护队数目
int dis[500]; //到达每个顶点的最短距离
int num[500]; //到达每个顶点的最短路径的数目
bool visited[500]; //是否已访问
int inf = 99999999; //无穷大

scanf("%d%d%d%d", &n, &m, &c1, &c2); //%d间不用加空格
for(int i = 0 ; i < n ; i++){
scanf("%d", &weight[i]);
}
fill(graph[0], graph[0]+500*500, inf); //二维数组 graph[0]!!!
fill(dis, dis+500, inf);
for(int i = 0 ; i < m ; i++){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
graph[a][b] = graph[b][a] = c; //无向图
}

dis[c1] = 0; //c1与自己距离为0
weight_[c1] = weight[c1]; //c1点救护队数目
num[c1] = 1; //到达c1路径数目

for(int i = 0 ; i < n ; i++){
int u = -1;
int minDis = inf; //记录最短的边 来确定下一个点

for(int j = 0 ; j < n ; j++){ //寻找距已遍历节点中最近的相邻节点 第一次u=起始点
if(visited[j] == false && dis[j] < minDis){
u = j;
minDis = dis[j];
}
}
if(u == -1) break;
visited[u] = true; //访问此点

for(int v = 0; v < n; v++){
if(visited[v] == false && graph[u][v] != inf){ //该节点未被访问 且 两节点间有通路
if(dis[u] + graph[u][v] < dis[v]){ //更新最短路径
dis[v] = dis[u] + graph[u][v];
num[v] = num[u]; //重置路径数目
weight_[v] = weight_[u] + weight[v];
}else if(dis[u] + graph[u][v] == dis[v]){ //最短路径数目增加
num[v] += num[u]; //最短路径数目=到v最短路径数目+到u最短路径数目
if(weight_[v] < weight_[u] + weight[v]){ //更新救护队数目最大值
weight_[v] = weight_[u] + weight[v];
}
}

}
}

}

printf("%d %d", num[c2], weight_[c2]);

return 0;
}