题目链接:https://pintia.cn/problem-sets/905631457273864192/problems/905631519127265289
题意:
本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。
输入格式:
输入在第一行给出两个正整数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 => ... => 终点
输入样例1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
5 4 0 2 3
5 9 1 1 4
0 6 0 1 1
7 3 1 1 2
8 3 1 1 2
2 5 0 2 2
2 1 1 1 1
1 5 0 1 3
1 4 0 1 1
9 7 1 1 3
3 1 0 2 5
6 3 1 2 1
5 3
输出样例1:
Time = 6: 5 => 4 => 8 => 3
Distance = 3: 5 => 1 => 3
输入样例2:
7 9
0 4 1 1 1
1 6 1 3 1
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 3 1
3 2 1 2 1
4 5 0 2 2
6 5 1 2 1
3 5
输出样例2:
Time = 3; Distance = 4: 3 => 2 => 5
代码:(迪杰斯特拉实现)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include<malloc.h>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i<r;i++)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int epg=10-8;
const int maxn=1000;
int n,m,S,D;//顶点数,边数
int e[maxn][maxn],e2[maxn][maxn];
int vis[maxn],d[maxn],pathcount[maxn],path[maxn],ren[maxn],acount[maxn],v[maxn],v2[maxn],pathd[maxn];
void dijiesi1(int s,int t)
{
for(int i=0; i<maxn; i++)
{
d[i]=inf;
vis[i]=0;
pathcount[i]=0;//在确保最短路的时候确保结点数最少
path[i]=-1;//记录路径
}
d[s]=0;
while(1)
{
int v=-1;
for(int i=0; i<n; i++)
{
if(!vis[i]&&(v==-1||d[i]<d[v]))
v=i;
}
if(v==-1)
break;
vis[v]=1;
for(int i=0; i<n; i++)
{
if(!vis[i])
{
if(d[i]>d[v]+e[v][i])
{
d[i]=d[v]+e[v][i];
path[i]=v;
pathcount[i]=pathcount[v]+1;//更新节点数
}
else if(d[i]==d[v]+e[v][i])//路长一样
{
if(pathcount[i]>pathcount[v]+1)
{
pathcount[i]=pathcount[v]+1;//则取节点数少的那条边
path[i]=v;
}
}
}
}
}
}
void dijiesi2(int s,int t)
{
for(int i=0; i<maxn; i++)
{
d[i]=inf;
vis[i]=0;
pathd[i]=0;//时间最快确保路径最短
path[i]=-1;
}
d[s]=0;
while(1)
{
int v=-1;
for(int i=0; i<n; i++)
{
if(!vis[i]&&(v==-1||d[i]<d[v]))
v=i;
}
if(v==-1)
break;
vis[v]=1;
for(int i=0; i<n; i++)
{
if(!vis[i])
{
if(d[i]>d[v]+e2[v][i])
{
d[i]=d[v]+e2[v][i];
path[i]=v; //记录路径
pathd[i]=pathd[v]+e[v][i]; //更新路径长度
}
else if(d[i]==d[v]+e2[v][i])
{
if(pathd[i]>pathd[v]+e[v][i])
{
//pathcount[i]=pathcount[v];
pathd[i]=pathd[v]+e[v][i]; //取路径长度小的
path[i]=v;
}
}
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
memset(e,inf,sizeof(e));
memset(e2,inf,sizeof(e2));
//memset(vis,0,sizeof(vis));
//memset(d,inf,sizeof(d));
memset(v,0,sizeof(v));
memset(v2,0,sizeof(v2));
for(int i=0; i<n; i++)
{
e[i][i]=0;
e2[i][i]=0;
}
for(int i=1; i<=m; i++)
{
int u,v,p,cost,time;
scanf("%d%d%d%d%d",&u,&v,&p,&cost,&time);
if(e[u][v]>cost)
{
if(p==0)
e[u][v]=e[v][u]=cost;
else
e[u][v]=cost;
}
if(e2[u][v]>time)
{
if(p==0)
e2[u][v]=e2[v][u]=time;
else
e2[u][v]=time;
}
}
scanf("%d%d",&S,&D);
dijiesi2(S,D);
//printf("Time = %d: ",d[D]);
int tt=d[D];
int sum=0,sum2=0;
int ans=D,ans2=D,DD=D;
while(path[D]!=-1)
{
//cout<<path[D]<<endl;
v[sum++]=path[D];
D=path[D];
}
//for(int i=sum-1;i>=0;i--)
//printf("%d => ",v[i]);
dijiesi1(S,DD);
int dd=d[DD];
while(path[DD]!=-1)
{
//cout<<path[D]<<endl;
v2[sum2++]=path[DD];
DD=path[DD];
}
//printf("%d\n",ans);
// for(int i=sum-1;i>=0;i--)
// cout<<v[i]<<" ";
// cout<<endl;
// for(int i=sum2-1;i>=0;i--)
// cout<<v2[i]<<" ";
// cout<<endl;
int flag=1;
// cout<<sum<<" "<<sum2<<endl;
if(sum2==sum)
{
for(int i=sum-1; i>=0; i--)
if(v[i]!=v2[i])
{
flag=0;
break;
}
}
else
flag=0;
if(flag)
{
printf("Time = %d; Distance = %d: ",tt,dd);
for(int i=sum-1; i>=0; i--)
printf("%d => ",v[i]);
printf("%d\n",ans);
}
else
{
printf("Time = %d: ",tt);
for(int i=sum-1; i>=0; i--)
printf("%d => ",v[i]);
printf("%d\n",ans);
printf("Distance = %d: ",dd);
for(int i=sum2-1; i>=0; i--)
printf("%d => ",v2[i]);
printf("%d\n",ans);
}
}
return 0;
}