1003 Emergency (25)(25 分)Dijkstra算法

1 题目

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (<= 500) - the number of cities (and the cities are numbered from 0 to N-1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.

Output

For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather.\ All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

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

题目链接 https://pintia.cn/problem-sets/994805342720868352/problems/994805523835109376

2 解题思路

  题目的大意是,你是救援小队的队长,现在有n个城市,每个城市有不同数量的救援小队,你位于c1,你需要奔赴c2,选择最短路径,并输出途径的救援小队的最大数量。
  感觉有点反人类,其实这是最常规的Dijkstra算法,仅需要遍历整个图得到最短路径,并保存最大权重即可。代码详解在注释中给出。

3 AC代码


/*
** @Brief:No.1003 of PAT advanced level. 
** @Author:Jason.Lee
** @Date:2018-7-2 
*/
#include
#include

#define CITY_NUM 501

using namespace std;

const int INF = 99999999;// 表示两点间不存在路径 
int road[CITY_NUM][CITY_NUM];//邻接矩阵法存储图,记录相邻点之间的路径
int weight[CITY_NUM];// 结点权重 
int dist[CITY_NUM];// 路径及权重 
int num[CITY_NUM];// 记录路径条数 
int w[CITY_NUM];	// 记录到达每个结点途径的救援队的数目总和 
bool visited[CITY_NUM];

int main(){	
	int n,m,c1,c2;
	while(cin>>n>>m>>c1>>c2){
		// 输入每个城市的急救中心数量 ,即结点权重 
		for(int i=0;i<n;i++){
			cin>>weight[i]; 
		}
		//初始化 
		fill(road[0],road[0]+CITY_NUM*CITY_NUM,INF);
		fill(dist,dist+CITY_NUM,INF);
		// 输入城市之间路线及距离,即路径权重 
		for(int i=0;i<m;i++){
			int city1;
			int city2;
			int dis;
			cin>>city1>>city2>>dis;
			road[city1][city2] = dis;
			road[city2][city1] = dis;
		}
		// 
		dist[c1] = 0;
		w[c1] = weight[c1];
		num[c1] = 1;
		// 开始进行Dijkstra 算法,计算最短路径 
		for(int i=0;i<n;i++){
			int visit = -1;// 当前访问结点
			int min = INF;// 最小权重值
			// 查找所有邻接点路径权重最小的点 
			for(int j=0;j<n;j++){
				if(visited[j] == false&&dist[j]<min){
					visit = j;
					min = dist[j];
				}
			}
			// 若查找失败,则无法到达目标点 
			if(visit==-1){
				break;
			}else{
				// 标记visit结点已遍历 
				visited[visit] = true;
			}
			// 计算visit邻接点路径权重最小的点 
			for(int v=0;v<n;v++){
				if(visited[v]==false&&road[visit][v]!=INF){
					// 如果邻接点v联通,且存在更小的路径,那么更新  
					if(dist[visit]+road[visit][v]<dist[v]){
						dist[v] = dist[visit]+road[visit][v];
						num[v] = num[visit];// 新结点路径更小,则更新 
						w[v] = w[visit]+weight[v];
					}else if(dist[visit]+road[visit][v]==dist[v]){
						num[v] +=num[visit];// 新结点路径相等,则存在多个等权重路径,做累加
						if(w[visit]+weight[v]>w[v]){
							// 记录较大权重者
							w[v] = w[visit]+weight[v]; 
						} 
					} 
				}
			} 
		} 
		cout<<num[c2]<<" "<<w[c2];
	}
	return 0;
}

你可能感兴趣的:(PAT-Advanced,Level)