【PAT】A1003 Emergency (25分)(最短路徑--難度中等)

1003 Emergency (25分)

題目鏈接

Problem Description
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 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

上一題比較基礎,可以參見上一題之後,再來思考本題,看是否有思路。
類型:最短路徑+第二標尺。
【標註】此類博文是爲了作者以後再想看時方便所寫,所以註釋和思路很少,有不便請見諒。

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

#define inf 1000000000
const int maxn = 505;
typedef long long ll;
int Graph[maxn][maxn];
ll d[maxn];
bool visit[maxn] = {false};

//題目要求
int N,M,C1,C2;
int weight[maxn];//每個城市的急救隊數量
int w[maxn];//記錄急救隊最多的數量 
int num[maxn];//記錄最短路徑條數 

void Dijkstra(int s)
{
	fill(d, d+N, inf);
	fill(w, w+N, 0);
	fill(num, num+N, 0);
	d[s] = 0;
	w[s] = weight[s];
	num[s] = 1;
	for(int i=0;i<N;i++)
	{
		int u=-1, MIN=inf;
		for(int j=0;j<N;j++)
		{
			if(visit[j]==false && d[j]<MIN)
			{
				MIN = d[j];
				u = j;
			}
		}
		if(u == -1)
			return ;
		visit[u] = true;
		for(int v=0;v<N;v++)
		{
			if(!visit[v] && Graph[u][v] != inf)
			{
				if(d[u]+Graph[u][v] < d[v]){
					d[v] = d[u] + Graph[u][v];
					w[v] = w[u] + weight[v];
					num[v] = num[u];
				}
				else if(d[v] == d[u]+Graph[u][v]){
					if(w[u] + weight[v] > w[v])
						w[v] = w[u] + weight[v];
					num[v] += num[u];
				}
			}
		}
	}
}

int main()
{
	fill(Graph[0], Graph[0]+maxn*maxn, inf);
	cin>>N>>M>>C1>>C2;
	for(int i=0;i<N;i++)
		cin>>weight[i];
	int a,b,x;
	for(int i=0;i<M;i++)
	{
		cin>>a>>b>>x;
		Graph[a][b] = Graph[b][a] = x;
	}
	Dijkstra(C1);
	cout<<num[C2]<<" "<<w[C2]<<endl;
	return 0;
}

更新:總結出這一類題的模板。

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

#define inf 1000000000
const int maxn = 505;
typedef long long ll;
int Graph[maxn][maxn];
ll d[maxn];
bool visit[maxn] = {false};
vector<int > pre[maxn];//記錄最短路徑各個頂點的前驅 

//題目要求
int N,M,C1,C2;
int weight[maxn];//每個城市的急救隊數量
int num =  0;//記錄最短路徑的條數 
ll optValue = -1;//最優值
vector<int >path, temp;//temp爲臨時路徑, path爲最短路徑 

//通用模板 
void Dijkstra(int s)
{
	fill(d, d+N, inf);
	d[s] = 0;
	for(int i=0;i<N;i++)
	{
		int u=-1, MIN=inf;
		for(int j=0;j<N;j++)
		{
			if(visit[j]==false && d[j]<MIN)
			{
				MIN = d[j];
				u = j;
			}
		}
		if(u == -1)
			return ;
		visit[u] = true;
		for(int v=0;v<N;v++)
		{
			if(!visit[v] && Graph[u][v] != inf)
			{
				if(d[u]+Graph[u][v] < d[v]){
					d[v] = d[u] + Graph[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if(d[v] == d[u]+Graph[u][v]){
					pre[v].push_back(u);
				}
			}
		}
	}
}

void Dfs(int s)
{
	if(s == C1)//注意這裏是倒着深搜,因爲起始點的前驅爲空
	{
		num++;//最短條數加1 
		temp.push_back(s);
		//計算最優
		ll value = 0;
		for(int i=0; i < temp.size(); i++)
			value += weight[temp[i]];			
		if(value > optValue)
			optValue = value;
		temp.pop_back();
		return;
	}
	temp.push_back(s);
	for(int i=0;i<pre[s].size();i++)
		Dfs(pre[s][i]);
	temp.pop_back();
}

int main()
{
	fill(Graph[0], Graph[0]+maxn*maxn, inf);
	cin>>N>>M>>C1>>C2;
	for(int i=0;i<N;i++)
		cin>>weight[i];
	int a,b,x;
	for(int i=0;i<M;i++)
	{
		cin>>a>>b>>x;
		Graph[a][b] = Graph[b][a] = x;
	}
	Dijkstra(C1);
	Dfs(C2);//注意這裏是倒着深搜,因爲起始點的前驅爲空
	cout<<num<<" "<<optValue<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章