PAT_甲级_1003 Emergency (25分) (C++)
原创
©著作权归作者所有:来自51CTO博客作者再见萤火虫IT的原创作品,请联系作者获取转载授权,否则将追究法律责任
目录
1,题目描述
题意解析:
输入:
输出:
2,思路
Dijkstra算法
注意点:
3,代码
1,题目描述

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:
题意解析:
目的城市发生事故,需要从所在城市赶往目的城市,寻找最短路径,并且在路中联系尽可能多的救护队前往救护。
题目保证任意两城市间至少有一条路
输入:
第一行:城市的数目N,路的数目M,所在城市编号C1,目的城市编号C2
第二行:N个城市对应各自救护队的数目
剩下M行:连接的两个城市编号C1、C2,及路的长度
输出:
从C1到C2不同最短路径的数目;
最短路径中可以集合的救护队的最多数目;
2,思路
意思很清楚,就是利用dijkstra算法;想再复习一下算法的同学可以戳这里@ heroacool 【数据结构--Dijkstra算法最清楚的讲解】
这里再简单描述一下:
Dijkstra算法
此算法用于解决图中从一点到其他所有顶点的最短路径问题;
- 从一个初始顶点出发,遍历邻近的所有顶点,取出最近的顶点放入visited中;
- 遍历visited数组中顶点邻近的所有顶点,找到最近的顶点放入visited中;
- 重复以上步骤2,直至所有顶点均遍历一遍;
注意点:
- 题目的限制,城市数量小于等于500;
- 注意记录最短路径的数目(小于当前最短路径时,更新;等于当前最短路径时,累加)和到达节点累加的点权值(小于当前最短路径时,更新;等于当前最短路径时,取最大值);
- 由于每个点的最短路径的数目和累加的点权值都需要记录,故均为他们开辟数组;
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;
}