L3-007 天梯地图 (基于优先队列和dijkstra实现)
本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。
输入格式:
输入在第一行给出两个正整数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 => ... => 终点
优先队列的使用技巧
priority_queue 默认是大顶堆,采用比较方式是 <
struct T{
int data;
friend bool operator < (const T& a,const T& b){
//默认是大顶(即返回 a.data < b.data ),取反为小顶
return a.data>b.data;
}
};
priority_queue<T> pq;//p按data小的在前
完整代码
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=500+1;
int g_len[N][N];
int g_time[N][N];
int graph_size;
int ans_min_tiem,ans_min_len;
void input_graph(){
int m;
cin>>graph_size>>m;
while(m--){
int v1,v2,one_way,length,time;
cin>>v1>>v2>>one_way>>length>>time;
g_len[v1][v2]=length;
g_time[v1][v2]=time;
if(one_way!=1){
g_len[v2][v1]=length;
g_time[v2][v1]=time;
}
}
}
/*如果最快到达路线不唯一,则输出几条最快路线中最短的那条*/
struct q_ele1{
int node;
int time;
int len;
friend bool operator<(const q_ele1&a,const q_ele1&b){
if(a.time==b.time){
return a.len>b.len;
}
else return a.time>b.time;
}
};
/*而如果最短距离的路线不唯一,则输出途径节点数最少的那条*/
struct q_ele2{
int node;
int len;
int cnt;
friend bool operator<(const q_ele2&a,const q_ele2&b){
if(a.len==b.len){
return a.cnt>b.cnt;
}
else return a.len>b.len;
}
};
vector<int> dijkstra1(int s,int e){
int t[N],d[N],path[N];
bool vis[N];
memset(t,-1,sizeof(t));
memset(d,-1,sizeof(d));
memset(vis,0,sizeof(vis));
priority_queue<q_ele1> p;
p.push({s,0,0});
t[s]=0;
d[s]=0;
while(!p.empty()){
auto cur=p.top();
p.pop();
if(vis[cur.node]) continue;
vis[cur.node]=true;
if(cur.node==e) break;
for(int i=0;i<graph_size;i++){
if(!vis[i]&&g_time[cur.node][i]){
if(t[i]==-1||cur.time+g_time[cur.node][i]<t[i]){
path[i]=cur.node;
// cout<<path[i];
t[i]=cur.time+g_time[cur.node][i];
d[i]=cur.len+g_len[cur.node][i];
p.push({i,t[i],d[i]});
}
else if(cur.time+g_time[cur.node][i]==t[i]&&cur.len+g_len[cur.node][i]<d[i]){
path[i]=cur.node;
// cout<<path[i];
d[i]=cur.len+g_len[cur.node][i];
p.push({i,t[i],d[i]});
}
}
}
}
ans_min_tiem=t[e];
vector<int> ans;
ans.push_back(e);
for(int i=path[e];i!=s;i=path[i]) ans.push_back(i);
ans.push_back(s);
reverse(ans.begin(),ans.end());
return ans;
}
vector<int> dijkstra2(int s,int e){
int cnt[N],d[N],path[N];
bool vis[N];
memset(d,-1,sizeof(d));
memset(cnt,-1,sizeof(cnt));
memset(vis,0,sizeof(vis));
priority_queue<q_ele2> p;
p.push({s,0,0});
d[s]=0;
cnt[s]=0;
while(!p.empty()){
auto cur=p.top();
p.pop();
if(vis[cur.node]) continue;
vis[cur.node]=true;
if(cur.node==e) break;
for(int i=0;i<graph_size;i++){
if(!vis[i]&&g_len[cur.node][i]){
if(d[i]==-1||cur.len+g_len[cur.node][i]<d[i]){
path[i]=cur.node;
d[i]=cur.len+g_len[cur.node][i];
cnt[i]=cur.cnt+1;
p.push({i,d[i],cnt[i]});
}
else if(cur.len+g_len[cur.node][i]==d[i]&&cur.cnt+1<cnt[i]){
path[i]=cur.node;
cnt[i]=cur.cnt+1;
p.push({i,d[i],cnt[i]});
}
}
}
}
ans_min_len=d[e];
vector<int> ans;
ans.push_back(e);
for(int i=path[e];i!=s;i=path[i]) ans.push_back(i);
ans.push_back(s);
reverse(ans.begin(),ans.end());
return ans;
}
void solve(){
int s,e;
cin>>s>>e;
auto path_1=dijkstra1(s,e);
auto path_2=dijkstra2(s,e);
cout<<"Time = "<<ans_min_tiem;
if(path_1!=path_2){
cout<<": "<<s;
for(int i=1;i<path_1.size();i++){
cout<<" => "<<path_1[i];
}
cout<<endl;
}
else{
cout<<"; ";
}
cout<<"Distance = "<<ans_min_len;
cout<<": "<<s;
for(int i=1;i<path_2.size();i++){
cout<<" => "<<path_2[i];
}
}
int main(){
input_graph();
solve();
return 0;
}