【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;
}
发布了52 篇原创文章 · 获赞 36 · 访问量 4481

猜你喜欢

转载自blog.csdn.net/qq_38861587/article/details/104883938