PAT甲级1003

该博客介绍了如何利用Dijkstra算法解决从特定起点到终点的最短路径问题,并在此基础上考虑了路径中所能聚集的最大救援队数量。博主详细解析了算法实现过程,包括初始化、路径更新和最短路径条数的处理,并提供了一个完整的C++代码示例来演示算法应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PAT甲级1003

题目大意:给出n座城市,m条边,开始的城市start以及目标城市end,第二行给出每座城市的救援队数量,接下来m行,每行给出一条边以及这条边的长度,求从start到end的最短路径条数,以及这些路径当中所能聚集到的最大救援队数量
主要用Dijkstra算法,开辟dis数组存放从start到每座城市的最短路径,rescue记录初始每座城市的救援队数量,maxrescue记录最短路径当中最大的救援队数量,num记录最短路径的条数,road记录每条路。这里要注意下num最短路径条数的处理,不是简单的重置1或者0,也不是自加加,要根据中介点u来判断当前路径条数的变化。例如处理j城时,如果通过中介u使得最短路径变小了则到j的最短路径就是u的最短路径条数;如果通过中介u变大了不做任何处理;如果相等则j的最短路径条数要再加上u的条数。

#include <iostream>
#include <vector>
#include <algorithm>
#define INF 100000000
#define MAXN 501
using namespace std;

int n,m;
int road[MAXN][MAXN];
int dis[MAXN],rescue[MAXN],maxrescue[MAXN],num[MAXN];
bool visit[MAXN]={false};
void init(){
	for(int i=0;i<n;i++){
		fill(road[i],road[i]+n,INF);
	}
	fill(visit,visit+n,false);
	fill(dis,dis+n,INF);
}
void Dijkstra(int start){
	dis[start]=0;
	num[start]=1;
	maxrescue[start]=rescue[start];
	for(int i=0;i<n;i++){
		int u=-1,min=INF;
		for(int j=0;j<n;j++){
			if(!visit[j]&&dis[j]<min){
				u=j;
				min=dis[j];
			}
		}
		if(u==-1) return ;
		visit[u]=true;
		for(int j=0;j<n;j++){
			if(!visit[j]&&road[u][j]<INF&&road[u][j]+dis[u]<=dis[j]){	//路径更新
				if(road[u][j]+dis[u]==dis[j]){	//最短路径相同时比较救援队数量
					num[j]+=num[u];	//若通过中介点找到的最短路径和不经过中介最短路径长度相同则到j最短路径条数加上u的最短路径条数
					if(maxrescue[u]+rescue[j]>maxrescue[j]) maxrescue[j]=maxrescue[u]+rescue[j];
				}
				else{	//最短路径更短时更新路径
					num[j]=num[u];	//若通过中介点找到的最短路径和不经过中介最短路径长度不同且更短则到j最短路径条数就是u的最短路径条数
					dis[j]=road[u][j]+dis[u];
					maxrescue[j]=maxrescue[u]+rescue[j];
				}
				
			}
		}
	}
}
int main(){
	int start,end,tmp,city1,city2,length;
	scanf("%d%d%d%d",&n,&m,&start,&end);
	init();
	for(int i=0;i<n;i++){
		scanf("%d",&tmp);
		rescue[i]=tmp;
	}
	for(int i=0;i<m;i++){
		scanf("%d%d%d",&city1,&city2,&length);
		road[city1][city2]=road[city2][city1]=length;
	}
	Dijkstra(start);
	printf("%d %d",num[end],maxrescue[end]);
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值