1. 程式人生 > >PAT (Advanced Level) 1003 Emergency (25 分)

PAT (Advanced Level) 1003 Emergency (25 分)

1003 Emergency (25 分)

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 Specification:

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, C​1​​ and C​2​​ - 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 C​1

​​, C​2​​ 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 C​1​​ to C​2​​.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C​1

​​ and C​2​​, 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

Code

#include <iostream>
#include <cstring>
using namespace std;

const int maxNumOfCity = 505;
const int INF = 0x3f3f3f3f;
int cityWeight[maxNumOfCity]; // 每個城市有的救援隊人數
int cityCost[maxNumOfCity][maxNumOfCity]; //鄰接矩陣,用以表示每個城市連線的關係
int dist[maxNumOfCity]; //記錄原點到其他城市的最短距離
int pathCount[maxNumOfCity], numOfMen[maxNumOfCity]; //記錄最短路徑的條數和延最短路徑所能集結到的救援隊人數
bool isVisit[maxNumOfCity]; //記錄每個節點(這裡指城市)是否被訪問過 
int numOfCity, numOfRoad; // 記錄實際城市數量和路的數量

void Dijkstra(int org); // 函式宣告

int main()
{
	int org, dst;
	cin >> numOfCity >> numOfRoad >> org >> dst; // 獲取輸入資料的第一行
	memset(isVisit, false, sizeof(isVisit));
	for (int i = 0; i < numOfCity; i++)
	{
		pathCount[i] = numOfMen[i] = 0;
		for (int j = 0; j < numOfCity; j++)
		{
			cityCost[i][j] = (i == j) ? 0 : INF;
		}
	}
	for (int i = 0; i < numOfCity; i++)
	{
		cin >> cityWeight[i]; //獲取輸入資料的第二行
	}
	for (int i = 0; i < numOfRoad; i++)
	{
		int start, end, cost;
		cin >> start >> end >> cost;
		cityCost[start][end]= cityCost[end][start]= cost; //獲取剩下的輸入資料
	}
	Dijkstra(org);
	cout << pathCount[dst] << " " << numOfMen[dst] << endl;
	return 0;
}

void Dijkstra(int org)
{
	//起點城市到起點城市
	pathCount[org] = 1; //有1條路
	numOfMen[org] = cityWeight[org]; //能集結到的救援人數就是城市駐紮的人數
	isVisit[org] = true;
	//初始化dist表
	for (int i = 0; i < numOfCity; i++)
	{
		dist[i] = cityCost[org][i];
		if (dist[i] != INF && i != org) //如果這個城市i可經由起點城市到達
		{
			numOfMen[i] = numOfMen[org] + cityWeight[i]; //可集結人數等於起點人數加城市i駐紮人數
			pathCount[i] = 1;
		}
	}

	for (int i = 0; i < numOfCity - 1; i++) //對於剩下的numOfCity-1個城市
	{
		//找到距離最近的城市pos
		int minDist = INF, pos = -1;
		for (int j = 0; j < numOfCity; j++)
		{
			if (!isVisit[j] && dist[j] < minDist)
			{
				minDist = dist[j];
				pos = j;
			}
		}
		isVisit[pos] = true;
		//更新dist表
		for (int j = 0; j < numOfCity; j++)
		{
			//如果城市沒被訪問過,而且起點到pos加從pos到j城市j的距離縮短
			if (!isVisit[j] && dist[pos] + cityCost[pos][j] < dist[j])
			{
				dist[j] = dist[pos] + cityCost[pos][j]; //更新從起點到j的最短距離
				numOfMen[j] = numOfMen[pos] + cityWeight[j]; //可集結的人數等於到pos集結的人數加j城本身駐紮的人數
				pathCount[j] = pathCount[pos];
			}
			//如果城市沒被訪問過,而且起點到pos加從pos到j城市j的距離與之前相等
			//表示又找到了一條新的最短路
			else if (!isVisit[j] && dist[pos] + cityCost[pos][j] == dist[j])
			{
				pathCount[j] += pathCount[pos]; //最短路數量相加加
				if (numOfMen[j] < numOfMen[pos] + cityWeight[j])
				{
					numOfMen[j] = numOfMen[pos] + cityWeight[j]; //更新可集結人數
				}
			}
		}
	}
	return;
}

思路

單源最短路徑問題,無負權重路徑,使用Dijkstra演算法。本解題思路詳見程式碼註釋。

另附:為什麼無窮大總是0x3f3f3f3f?
https://blog.csdn.net/hurmishine/article/details/51946015

以上