【PAT - 甲级1003】Emergency (25分)(Dijkstra,最短路条数,双权值最短路)

题干:

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

题目大意:

作为一个城市的紧急救援队队长,你会得到一份特殊的国家地图。这张地图显示了由一些道路连接起来的几个分散的城市。地图上标明了每个城市的救援队数量和每对城市之间的道路长度。当从其他城市接到紧急电话时,你的工作就是尽快把你的人带到那个地方,同时在路上尽可能多地召集人手。

一句话题意:给定一张无向图,给定起点和终点,点有点权,边有边权,求两点之间最短路条数,并求出在最短路的条件下路径的点权和的最大值。

解题报告:

不得不说,,,几年前的PAT考题确实比现在要难得多,这题虽然是裸题,但是代码量也不小了,竟然才是25分题。

直接Dijkstra搞双权值的就行,记得点编号是0~N-1的,所以要先转化到1~N。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
const int INF = 0x3f3f3f3f;
int n,m,st,ed,val[MAX];
struct Edge {
	int v,ne,w;
} e[MAX*2];
int head[MAX],tot;
void add(int u,int v,int w) {
	e[++tot].v = v;
	e[tot].w = w;
	e[tot].ne = head[u];
	head[u] = tot;
}
struct Point {
	int pos,c;
	Point(){}
	Point(int pos,int c):pos(pos),c(c){}
	bool operator<(const Point & b) const {
		return c > b.c; 
	}
};
priority_queue<Point> pq; 
int dis[MAX],vis[MAX],ans[MAX],Max[MAX];
void Dij() {
	for(int i = 1; i<=n; i++) dis[i] = INF,vis[i] = 0,ans[i] = 0,Max[i] = 0;
	pq.push(Point(st,0)); dis[st] = 0; ans[st] = 1; Max[st] = val[st];
	while(pq.size()) {
		Point cur = pq.top();pq.pop();
		if(vis[cur.pos] == 1) continue;
		vis[cur.pos] = 1;
		for(int i = head[cur.pos]; ~i; i = e[i].ne) {
			int v = e[i].v;
			if(vis[v]) continue;
			if(dis[v] > dis[cur.pos] + e[i].w) {
				dis[v] = dis[cur.pos] + e[i].w;
				ans[v] = ans[cur.pos];
				Max[v] = Max[cur.pos] + val[v];
				pq.push(Point(v,dis[v]));
			}
			else if(dis[v] == dis[cur.pos] + e[i].w) {
				ans[v] += ans[cur.pos];
				Max[v] = max(Max[v],Max[cur.pos] + val[v]);
			}
		}
	}
}
int main()
{
	cin>>n>>m>>st>>ed; st++,ed++; 
	for(int i = 1; i<=n; i++) cin>>val[i],head[i] = -1;
	for(int u,v,w,i = 1; i<=m; i++) {
		scanf("%d%d%d",&u,&v,&w); u++,v++;
		add(u,v,w);add(v,u,w);
	}
	Dij();
	printf("%d %d\n",ans[ed],Max[ed]);
	return 0 ;
}
发布了1106 篇原创文章 · 获赞 122 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/qq_41289920/article/details/104163151
今日推荐