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;
}```