天梯赛天梯地图

该博客介绍了如何利用Dijkstra算法实现一个在线地图服务,该服务能根据用户输入的起点和终点,推荐最快到达和最短距离的两条路线。文章详细阐述了算法思路,即先以时间优先级进行搜索找到最快路线,再以路径优先级寻找最短距离路线。在处理可能存在的多种最快路线和最短距离路线时,分别选取路径最短的最快路线和途径节点最少的最短距离路线。最后,提供了完整的C++代码实现。
摘要由CSDN通过智能技术生成

7-30 天梯地图 (30 分)
本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。

输入格式:
输入在第一行给出两个正整数N(2 ≤ N ≤ 500)和M,分别为地图中所有标记地点的个数和连接地点的道路条数。随后M行,每行按如下格式给出一条道路的信息:

V1 V2 one-way length time
其中V1和V2是道路的两个端点的编号(从0到N-1);如果该道路是从V1到V2的单行线,则one-way为1,否则为0;length是道路的长度;time是通过该路所需要的时间。最后给出一对起点和终点的编号。

输出格式:
首先按下列格式输出最快到达的时间T和用节点编号表示的路线:

Time = T: 起点 => 节点1 => … => 终点
然后在下一行按下列格式输出最短距离D和用节点编号表示的路线:

Distance = D: 起点 => 节点1 => … => 终点
如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。

如果这两条路线是完全一样的,则按下列格式输出:

Time = T; Distance = D: 起点 => 节点1 => … => 终点

思路:跑两遍djkstra,第一遍将时间作为第一优先度,若时间相同则考虑路径,第二遍将路径作为第一优先度,若路径相同则考虑节点个数,用滚动数组存节点。
代码:

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define pi 3.141592653589
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=0x7f7f7f7f;
const int maxn=510;
const ll mod=1e9+7;
ll read() {
	ll f=0,x=0;
	char ch=getchar();
	while(!isdigit(ch)) {
		if(ch=='-') f=1;
		ch=getchar();
	}
	while(isdigit(ch)) {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return !f?x:-x;
}
ll qpow(ll a,ll b,ll p) {
	ll ans=1;
	while(b) {
		if(b&1) ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans%p;
}
vector<int> v1,v2;
int sum[maxn],pre1[maxn],pre2[maxn];
int dis1[maxn],dis2[maxn],g1[maxn][maxn],g2[maxn][maxn];
int m,n;
int s,d;
bool st[maxn];
void djkstra1(){
	//优先时间 再路径 
	memset(dis1,0x3f,sizeof dis1);
    memset(dis2,0x3f,sizeof dis2);
	dis1[s]=0,dis2[s]=0;
	for(int i=1;i<=n;i++){
		int t=-1;
		for(int j=0;j<n;j++){
			if(!st[j]&&(t==-1||dis1[j]<dis1[t])){
				t=j;
			}
		}
		st[t]=true;
		for(int j=0;j<n;j++){
			if(dis1[j]>dis1[t]+g1[t][j]){
				pre1[j]=t;
				dis1[j]=dis1[t]+g1[t][j];
				dis2[j]=dis2[t]+g2[t][j]; //长度 
			}
			else if(dis1[j]==dis1[t]+g1[t][j]){
// 				dis1[j]=dis1[t]+g1[t][j];
				if(dis2[j]>dis2[t]+g2[t][j]){
					pre1[j]=t;
					dis2[j]=dis2[t]+g2[t][j]; 
				}
			}
		}
	}
	int end=d;
	while(end!=s){
		v1.push_back(end);
		end=pre1[end];
//         cout<<end<<endl;
	}
    v1.push_back(s);
}
void djkstra2(){
	// 优先路径 再节点数量 
    memset(sum,0,sizeof sum);
	memset(st,false,sizeof st);
	memset(dis2,0x3f,sizeof dis2);
	dis2[s]=0;
	sum[s]=1;
	for(int i=1;i<=n;i++){
		int t=-1;
		for(int j=0;j<n;j++){
			if(!st[j]&&(t==-1||dis2[j]<dis2[t])){
				t=j;
			}
		}
		st[t]=1;
		for(int j=0;j<n;j++){
			if(dis2[j]>dis2[t]+g2[t][j]){
				dis2[j]=dis2[t]+g2[t][j];
				sum[j]=sum[t]+1;
				pre2[j]=t;
			}
			else if(dis2[j]==dis2[t]+g2[t][j]){
// 				dis2[j]=dis2[t]+g2[t][j];
				if(sum[j]>sum[t]+1){
					sum[j]=sum[t]+1;
					pre2[j]=t;
				}
			}
		}
	}
	int end=d;
	while(end!=s){
		v2.push_back(end);
		end=pre2[end];
	}
	v2.push_back(s);
}
int main() {
	memset(g1,0x3f,sizeof g1);
	memset(g2,0x3f,sizeof g2); 
	cin>>n>>m;
	while(m--){
		int a,b,on,c,w;
		cin>>a>>b>>on>>c>>w;
		g2[a][b]=min(g2[a][b],c); //长度 
		g1[a][b]=min(g1[a][b],w); //时间 
		if(!on){
			g1[b][a]=w;
			g2[b][a]=c;
		}
	} 
    cin>>s>>d;
	djkstra1();
	djkstra2();
    int time=dis1[d];
	int lenth=dis2[d];
    if(v1==v2){
        printf("Time = %d; Distance = %d: ",time,lenth);
        for(int i=v1.size()-1;i>=0;i--){
        	cout<<v1[i];
        	if(i!=0){
        		cout<<" => ";
			}
		}
        puts("");
    }
    else{
        printf("Time = %d: ",time);
        for(int i=v1.size()-1;i>=0;i--){
        	cout<<v1[i];
        	if(i!=0){
        		cout<<" => ";
			}
		}
        puts("");
        printf("Distance = %d: ",lenth);
        for(int i=v2.size()-1;i>=0;i--){
        	cout<<v2[i];
        	if(i!=0){
        		cout<<" => ";
			}
		}
    }

	return 0;
}```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值