[PAT]甲级 1003 Emergency

问题翻译:

1003 紧急情况

作为某城市的紧急救援小组的组长,你得到了一张关于你所在国家的“特殊”地图。地图显示了分散的城市和他们之间的道路,并且标出了每个城市求援队伍的数量和道路的长度。当你接到其他城市的救援电话的时候,你的任务是尽可能快地带领你的队员到达那个城市并且在去的路上尽可能召集更多的人手。

Input

每个输入文件包含一个测试例子。对于每个测试例子,第一行包含4个正整数:N(<=500)城市的数量(城市的标号则是0~N-1),M-道路的数量, C1和C2-分别是你所在城市的标号和你要去救援的城市的标号。第二行包含N个整数,代表第i个城市中救援队的数量。接下来M行描述M条道路信息包含三个整数c1,c2和L,分别代表道路两端的城市标号和道路长度。要保证C1到C2至少有一条路。

Output

对于每个测试例子,输出打印一行包含两个数:C1到C2最短路径的数量和可聚集的救援队伍最大数量。所有数由一个空格分开并且在末尾没有多余的空格。

代码:

#include<iostream>

using namespace std;
#define MAX_CITY_NUM 501
#define INFINITY 100000000
#define AdjMatrix int

/*结构体定义*/
typedef struct node {
	int weight;/*救援队伍的数目*/
}City;
typedef struct graph {
	City citys[MAX_CITY_NUM];/*顶点向量*/
	AdjMatrix roads[MAX_CITY_NUM][MAX_CITY_NUM];/*邻接矩阵*/
	int city_num, road_num;/*城市数目和道路数目*/
}Map;

Map map;
int dist[MAX_CITY_NUM];/*最短距离*/
int path_num[MAX_CITY_NUM];/*最短路径数量*/
int max_road_count[MAX_CITY_NUM];/*最短路径中最大救援数量*/
bool visit[MAX_CITY_NUM];/*标记顶点是否已经有最短路径*/
/**

*/
Map initialize(Map map) {
	/*给顶点数组赋值*/
	for (int i = 0; i < map.city_num; i++)
		cin >> map.citys[i].weight;
	/*初始化邻接矩阵*/
	for (int i = 0; i < MAX_CITY_NUM; i++)
	{
		for (int j = 0; j < MAX_CITY_NUM; j++)
			map.roads[i][j] = (i == j)? 0 : INFINITY;
	}
	/*给邻接 矩阵赋值*/
	for (int j = 0; j < map.road_num; j++)
	{
		int c1, c2, weight;
		cin >> c1 >> c2 >> weight;
		map.roads[c1][c2] = weight;
		map.roads[c2][c1] = weight;
	}
	return map;
}
/*

*/
void Relax(Map map, int u, int v) {
	if (dist[v] > dist[u] + map.roads[u][v]) {
		dist[v] = dist[u] + map.roads[u][v];
		path_num[v] = path_num[u];
		max_road_count[v] = max_road_count[u] + map.citys[v].weight;
	}
	else if (dist[v] == dist[u] + map.roads[u][v]) {
		path_num[v] = path_num[u] + path_num[v] ;
		if (max_road_count[v] < max_road_count[u] + map.citys[v].weight)
			max_road_count[v] = max_road_count[u] + map.citys[v].weight;
	}
}

/*

*/
void Dijkstra(Map map,int c1) {
	/*初始化*/
	for (int i = 0; i < map.city_num; i++) {
		visit[i] = false;
		path_num[i] = 0;
		max_road_count[i] = 0;
		dist[i] = INFINITY;
	}
	/*源点单独初始化*/
	dist[c1] = 0;
	path_num[c1] = 1;
	max_road_count[c1] = map.citys[c1].weight;
	
	for (int i = 0; i < map.city_num; i++) {

		/*寻找未访问顶点中最短路径距离最小的顶点*/
		int u;//未访问顶点中最短路径距离最小的顶点
		int minpath = INFINITY;
		for (int j = 0; j < map.city_num; j++) {
			if (!visit[j] && dist[j] < minpath) {
				u = j;
				minpath = dist[j];
			}
		}
		/*将距离最小的点加入集合S中*/
		visit[u] = true;

		/*将与u相连的顶点松弛,为了减少不必要的松弛,加了不在S中的条件*/
		for (int j = 0; j < map.city_num; j++) {
			if (!visit[j] && map.roads[u][j] != INFINITY) {
				Relax(map, u, j);
			}
		}
	}
}

int main() {
	int C1, C2;
	cin >> map.city_num >> map.road_num >> C1 >> C2;
	map = initialize(map);
	Dijkstra(map, C1);
	cout << path_num[C2] << " " << max_road_count[C2] << endl;
	return 0;
}

结果:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值