3069. 网红重庆1最短路径问题SPFA queue 链表

这篇博客介绍了如何解决网红城市重庆的最短路径问题,考虑海拔变化因素。利用SPFA(Shortest Path Faster Algorithm)算法寻找从地点C到D的路径中,海拔变化总和最小的路径。博客提供了输入数据格式和样例输入、输出,帮助读者理解算法的应用。

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

  1. 网红重庆1
    【问题描述】

网红城市——重庆,堪称一座8D的魔幻大都市,明明(不要问我明明是谁?)在一楼上的电梯,到了11楼出电梯又是一楼。

假设重庆有N个地点,给出各个地点的海拔高度,各个地点之间可能有双向的路径连接,或者单向的路径连接。有一个外地人来重庆,要从地点C到D,但他对爬坡下坎很不习惯,请帮他在从C到D所有路径中,找一条海拔变化(海拔降低或升高都视为正的值)最小的路径,即组成路径的各条直接路径海拔变化的总和最小。

【输入形式】

输入文件包含多个测试数据。每个测试数据第1行是两个整数N和M,N表示地点的数目,5≤N≤50,地点的序号从1开始计起,M表示这N个地点之间直接路径的数目,对任意两个地点A、B,A和B之间有一条双向直接路径、从A到B有一条单向直接路径、从B到A有一条单向直接路径,这3种情形最多只出现一种情形,测试数据保证这N个地点之间是互相可达的(再啷个爬坡下坎,总还是走得到的);第2行有N个整数,表示这N个地点的海拔高度,范围在[100, 1000],可能存在相同海拔高度的地点;接下来有M行,描述了M条直接路径,格式为“1 A B”或“2 A B”,前者表示从地点A到地点B的一条单向直接路径,后者表示地点A和B之间的一条双向直接路径,A和B为地点的序号,A≠B;每个测试数据的最后一行为两个整数C和D,表示那个外地人要从地点C到D,C和D为地点的序号,C≠D。测试数据保证地点序号都是有效的。

输入文件最后一行为0 0,代表输入结束。

【输出形式】

对每个测试数据,输出占一行,为求得的从地点C到D的各条路径中海拔变化总和的最小值。

【样例输入】

5 5

100 160 230 450 120

2 1 2

1 1 5

2 2 5

2 3 4

2 4 5

1 3

0 0

【样例输出】

570

#include<bits/stdc++.h>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 100
struct node
{
	int t;
	int w;
	node*next;
};
queue<int>q;
int n,N;
node*List[MAXN];
int inq[MAXN];
int d[MAXN];
int p[MAXN];
int a[MAXN];//海拔高度 
void spfa(int src)
{
	int i,u;//u为队列头顶点序号
	node*t;
	for(i=1;i<=N;i++)
	{
		d[i]=INF;p[i]=src;inq[i]=0;
	}
	d[src]=0;p[src]=src;inq[src]++;
	q.push(src);
	while(!q.empty())
	{
		u=q.front();q.pop();inq[u]--;
		t=List[u];
		while(t!=NULL)
		{
			int v=t->t;
			if(d[v]>d[u]+t->w)
			{
				d[v]=d[u]+t->w;p[v]=u;
				if(!inq[v]){q.push(v);inq[v]++;}
			}
			t=t->next;
		}
	} 
}
int main()
{
	int M,i,j,r,C,D;//N个地点,M条路 //从C到D 
	int u,v;//,w;
	node*t;
	//memset(List,0,sizeof(List));
	while(1)
	{
	  	scanf("%d%d",&N,&M);
	  	if(!N)break;
		for(i=1;i<=N;i++)scanf("%d",&a[i]);
	//	cout<<"222"<<endl;
		for(j=1;j<=M;j++)
		{
			scanf("%d%d%d",&r,&u,&v);//输入并生成地图 
			t=new node;
			if(r==1)
			{
			t->t=v;
			t->w=abs(a[v]-a[u]);
			t->next=NULL;
			if(List[u]==NULL)List[u]=t;
			else {t->next=List[u];List[u]=t;}
			}
			else if(r==2)
			{
			t->t=v;
			t->w=abs(a[v]-a[u]);
			t->next=NULL;
			if(List[u]==NULL)List[u]=t;
			else {t->next=List[u];List[u]=t;}
			t=new node;
			t->t=u;
			t->w=abs(a[v]-a[u]);
			t->next=NULL;
			if(List[v]==NULL)List[v]=t;
			else {t->next=List[v];List[v]=t;}
			}
		}
		scanf("%d %d",&C,&D);
		spfa(C);
		for(j=1;j<=N;j++)//释放链表空间 
		{
			t=List[j];
			while(t)
			{
				List[j]=t->next;delete t;t=List[j];
			}
		}
	//	if(d[D]<1000)
		printf("%d\n",d[D]);
	//	else 
		//printf("INF\n"); 
	}
	return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值