PAT 甲级 1003 Emergency

一、题目描述

请添加图片描述
题目描述的大致意思是:作为一个城市的紧急救援队领导,你得到了一份特殊的国家地图。地图上显示有几个分散的城市,它们之间由一些道路连接。地图上标记了每个城市的救援队数量以及任意两个城市之间道路的长度。当你从其他城市接到紧急呼叫时,你的任务是尽快带领你的队伍到达目的地,并在途中召集尽可能多的援助。
有N个城市,M个路,L是路的长度,C1是起点,C2是终点

二、题目分析

要求一个起点到另一个终点的最短路径数目和最大权重,用迪杰斯特拉算法。

三、AC代码

#include<iostream>
#include<limits.h>
#include<math.h>
using namespace std;
const int MAXN = 501;//防止溢出
const int INF = numeric_limits<int>::max();//最大值
int e[MAXN][MAXN], weight[MAXN], dis[MAXN], w[MAXN], num[MAXN];
//e[i][j]表示边i-j的权值,weight[i]表示i点的权重,dis[i]表示从起点到i点的最短路径
//w[i]表示从起点到i点的最大权重和(包含起点和终点),num[i]表示从起点到i点的路径数
bool visit[MAXN];
//是否激活,避免形成环路
int main() {
	int n,m,c1,c2;
	cin >> n >> m >> c1 >> c2;
	//输入节点个数,边个数,起点,终点
	fill(&e[0][0], &e[0][0] + MAXN * MAXN, INF);
	fill(dis, dis + MAXN, INF);
	//初始化边权值和最短路径都为INF,其他全局变量默认值为0不需要初始化
	for (int i = 0; i < n; i++) {
		cin >> weight[i];
	}
	for (int i = 0; i < m; i++) {
		int x, y, ed;
		cin >> x >> y >> ed;
		e[x][y] = e[y][x] = ed;
	}
	//输入已知边权值和权重
	dis[c1] = 0;
	num[c1] = 1;
	w[c1] = weight[c1];
	//初始化起点相关值
	for (int i = 0; i < n; i++) {
		int u = -1, minn = INF;
		//u是未激活中的距离起始节点最短的节点,minn是目前已知最短距离
		for (int j = 0; j < n; j++) {
			if (visit[j] == false && minn > dis[j]) {//判断:未被激活且路径最短
				u = j;
				minn = dis[j];
			}//寻找在未被激活的节点中,距离起始节点最短的节点,并记录距离
		}
		if (u == -1) break;
		visit[u] = true;
		//标记节点已经激活
		for (int k = 0; k < n; k++) {
			if (visit[k] == false && e[u][k] != INF) {//对u节点到其他未被激活节点的数据进行更新
				if (dis[u] + e[u][k] < dis[k]) {//起点到u+u到k路径 < 起点到k路径,则经过u到k路径更短
					dis[k] = dis[u] + e[u][k];//更新最短路径
					num[k] = num[u];
					w[k] = w[u] + weight[k];
				}
				else if (dis[u] + e[u][k] == dis[k]) {//若两路径相等
					num[k] += num[u];
					w[k] = fmax(w[k], w[u] + weight[k]);
				}
			}
		}
	}
	cout << num[c2] << " " << w[c2];//输出
	return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值