PAT 1111 Online Map[Dijkstra][dfs]
1111 Online Map(30 分)
Input our current position and a destination, an online map can recommend several paths. Now your job is to recommend two paths to your user: one is the shortest, and the other is the fastest. It is guaranteed that a path exists for any request.
Input Specification:
Each input file contains one test case. For each case, the first line gives two positive integers N (2≤N≤500), and M, being the total number of streets intersections on a map, and the number of streets, respectively. Then M lines follow, each describes a street in the format:
V1 V2 one-way length time
where V1 and V2 are the indices (from 0 to N−1) of the two ends of the street; one-way is 1 if the street is one-way from V1 to V2, or 0 if not; length is the length of the street; and time is the time taken to pass the street.
Finally a pair of source and destination is given.
Output Specification:
For each case, first print the shortest path from the source to the destination with distance D in the format:
Distance = D: source -> v1 -> ... -> destination
Then in the next line print the fastest path with total time T:
Time = T: source -> w1 -> ... -> destination
In case the shortest path is not unique, output the fastest one among the shortest paths, which is guaranteed to be unique. In case the fastest path is not unique, output the one that passes through the fewest intersections, which is guaranteed to be unique.
In case the shortest and the fastest paths are identical, print them in one line in the format:
Distance = D; Time = T: source -> u1 -> ... -> destination
Sample Input 1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
3 4 0 3 2
3 9 1 4 1
0 6 0 1 1
7 5 1 2 1
8 5 1 2 1
2 3 0 2 2
2 1 1 1 1
1 3 0 3 1
1 4 0 1 1
9 7 1 3 1
5 1 0 5 2
6 5 1 1 2
3 5
Sample Output 1:
Distance = 6: 3 -> 4 -> 8 -> 5
Time = 3: 3 -> 1 -> 5
Sample Input 2:
7 9
0 4 1 1 1
1 6 1 1 3
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 1 3
3 2 1 1 2
4 5 0 2 2
6 5 1 1 2
3 5
Sample Output 2:
Distance = 3; Time = 4: 3 -> 2 -> 5
题目大意:在图中,给出当前所占的点与目的地,输入最短的路径和最快的路径这两条,并且这两条一定存在,路径分为单行道和双行道。如果最短路径不唯一,那么输出最短路径中最快的一个;最快的路径中不唯一,那么输出最快路径中经过节点最少的一个。如果最短和最快路径相同,那么输出在一行之内。
//这个就是两个迪杰斯特拉,我待会写一下,感觉还是控制不住。
//第一次写成了这样,第二个测试点过不去,答案错误。
#include <iostream>
#include <vector>
#include<cstdio>
using namespace std;
#define INF 99999
//vector<int> v[501];//这个是一个邻接表,来存储图
int vlen[][],vtm[][];//这两个分别用来存储路径长度和路径时间
//这个初始化为inf,然后输入直接就可以表示图啊。。。
vector<int> ctmpath,tmpath;
vector<int> clenpath,lenpath;
int minLen=INF,minTm=INF;
int dis[],tim[],vis[];
int from,to;
vector<int> prel[],pret[];
void dfsl(int f){
if(f==from){
//计算最短时间,最短距离肯定都一样了,
int t=;
for(int i=;i<clenpath.size()-;i++){
t+=vtm[clenpath[i+]][clenpath[i]];
}
if(t<minTm){
minTm=t;
lenpath=clenpath;
}
return ;
}
for(int i=;i<prel[f].size();i++){
clenpath.push_back(prel[f][i]);//这里不用再标记是否等于0了。
dfsl(prel[f][i]);
clenpath.pop_back();
}
}
void dfst(int f){
if(f==from){
int l=;
for(int i=;i<ctmpath.size()-;i++){
l+=vlen[ctmpath[i+]][ctmpath[i]];
}
if(l<minLen)
{
minLen=l;
tmpath=ctmpath;
}
return ;
}
for(int i=;i<pret[f].size();i++){
ctmpath.push_back(pret[f][i]);
dfst(pret[f][i]);
ctmpath.pop_back();
}
}
int main() {
int n,m;
cin>>n>>m;
int one,length,time;
fill(dis,dis+,INF);//2.这里全部得初始化。
fill(tim,tim+,INF);
fill(vlen[],vlen[]+*,INF);
fill(vtm[],vtm[]+*,INF);//这个地方原来只写了501。。。怎么能就初始化这一点地方呢
for(int i=;i<m;i++){
cin>>from>>to>>one>>length>>time;
vlen[from][to]=length;
vtm[from][to]=time;
if(one==){//双行道
vlen[to][from]=length;
vtm[to][from]=time;
}
}
cin>>from>>to;
//初始化?
dis[from]=;
for(int i=;i<n;i++){
int minx=INF,u=-;
for(int j=;j<n;j++){
if(vis[j]==&&dis[j]<minx){
minx=dis[j];
u=j;
}
}
if(u==-)break;
vis[u]=;
for(int j=;j<n;j++){//使用邻接矩阵来存储的。
if(vis[j]==&&vlen[u][j]!=INF){
if(dis[j]>dis[u]+vlen[u][j]){
dis[j]=dis[u]+vlen[u][j];
prel[j].clear();
prel[j].push_back(u);//在这里可以用一个数组来记录时间的,
//这样的话下一个if就可以判断,是否根据时间更新前驱。
//cout<<x<<" "<<u<<'\n';
}else if(dis[j]==dis[u]+vlen[u][j]){
prel[j].push_back(u);
}
}
}
}
clenpath.push_back(to);
//dfsl(from);//应该是从后往前的前驱啊!不是这样的
dfsl(to);
//接下来求最短时间了
tim[from]=;
fill(vis,vis+,);
for(int i=;i<n;i++){
int minx=INF,u=-;
for(int j=;j<n;j++){
if(vis[j]==&&tim[j]<minx){
minx=tim[j];
u=j;
}
}
if(u==-)break;
vis[u]=;//我的天,忘了加这一句了。
for(int j=;j<n;j++){
if(vis[j]==&&vtm[u][j]!=INF){
if(tim[j]>tim[u]+vtm[u][j]){
tim[j]=tim[u]+vtm[u][j];
pret[j].clear();
pret[j].push_back(u);
}else if(tim[j]==tim[u]+vtm[u][j]){
pret[j].push_back(u);
}
}
} }
ctmpath.push_back(to);
dfst(to);
if(lenpath==tmpath){
printf("Distance = %d; Time = %d: ",dis[to],tim[to]);
printf("%d",from);
for(int i=lenpath.size()-;i>=;i--){
printf(" -> %d",lenpath[i]);
}
}else{
printf("Distance = %d: ",dis[to]);
printf("%d",from);
for(int i=lenpath.size()-;i>=;i--)
printf(" -> %d",lenpath[i]);
printf("\n");
printf("Time = %d: ",tim[to]);
printf("%d",from);
for(int i=tmpath.size()-;i>=;i--)
printf(" -> %d",tmpath[i]);
}
return ;
}
又看了一边题目,发现是理解错题意了,在最短时间相同的路径时,需要经过节点数最少,而不是距离最短,理解偏这么多,还能过那么多测试点。。
下面是AC30分的,
#include <iostream>
#include <vector>
#include<cstdio>
using namespace std;
#define INF 99999
//vector<int> v[501];//这个是一个邻接表,来存储图
int vlen[][],vtm[][];//这两个分别用来存储路径长度和路径时间
//这个初始化为inf,然后输入直接就可以表示图啊。。。
vector<int> ctmpath,tmpath;
vector<int> clenpath,lenpath;
int minLen=INF,minTm=INF;
int dis[],tim[],vis[];
int from,to;
vector<int> prel[],pret[];
void dfsl(int f){
if(f==from){
//计算最短时间,最短距离肯定都一样了,
int t=;
for(int i=;i<clenpath.size()-;i++){
t+=vtm[clenpath[i+]][clenpath[i]];
}
if(t<minTm){
minTm=t;
lenpath=clenpath;
}
return ;
}
for(int i=;i<prel[f].size();i++){
clenpath.push_back(prel[f][i]);//这里不用再标记是否等于0了。
dfsl(prel[f][i]);
clenpath.pop_back();
}
}
void dfst(int f){
if(f==from){
if(tmpath.size()==){
tmpath=ctmpath;
}else if(tmpath.size()>ctmpath.size()){
tmpath=ctmpath;
}
return ;
}
for(int i=;i<pret[f].size();i++){
ctmpath.push_back(pret[f][i]);
dfst(pret[f][i]);
ctmpath.pop_back();
}
}
int main() {
int n,m;
cin>>n>>m;
int one,length,time;
fill(dis,dis+,INF);//2.这里全部得初始化。
fill(tim,tim+,INF);
fill(vlen[],vlen[]+*,INF);
fill(vtm[],vtm[]+*,INF);//这个地方原来只写了501。。。怎么能就初始化这一点地方呢
for(int i=;i<m;i++){
cin>>from>>to>>one>>length>>time;
vlen[from][to]=length;
vtm[from][to]=time;
if(one==){//双行道
vlen[to][from]=length;
vtm[to][from]=time;
}
}
cin>>from>>to;
//初始化?
dis[from]=;
for(int i=;i<n;i++){
int minx=INF,u=-;
for(int j=;j<n;j++){
if(vis[j]==&&dis[j]<minx){
minx=dis[j];
u=j;
}
}
if(u==-)break;
vis[u]=;
for(int j=;j<n;j++){//使用邻接矩阵来存储的。
if(vis[j]==&&vlen[u][j]!=INF){
if(dis[j]>dis[u]+vlen[u][j]){
dis[j]=dis[u]+vlen[u][j];
prel[j].clear();
prel[j].push_back(u);//在这里可以用一个数组来记录时间的,
//这样的话下一个if就可以判断,是否根据时间更新前驱。
//cout<<x<<" "<<u<<'\n';
}else if(dis[j]==dis[u]+vlen[u][j]){
prel[j].push_back(u);
}
}
}
}
clenpath.push_back(to);
//dfsl(from);//应该是从后往前的前驱啊!不是这样的
dfsl(to);
//接下来求最短时间了
tim[from]=;
fill(vis,vis+,);
for(int i=;i<n;i++){
int minx=INF,u=-;
for(int j=;j<n;j++){
if(vis[j]==&&tim[j]<minx){
minx=tim[j];
u=j;
}
}
if(u==-)break;
vis[u]=;//我的天,忘了加这一句了。
for(int j=;j<n;j++){
if(vis[j]==&&vtm[u][j]!=INF){
if(tim[j]>tim[u]+vtm[u][j]){
tim[j]=tim[u]+vtm[u][j];
pret[j].clear();
pret[j].push_back(u);
}else if(tim[j]==tim[u]+vtm[u][j]){
pret[j].push_back(u);
}
}
} }
ctmpath.push_back(to);
dfst(to);
if(lenpath==tmpath){
printf("Distance = %d; Time = %d: ",dis[to],tim[to]);
printf("%d",from);
for(int i=lenpath.size()-;i>=;i--){
printf(" -> %d",lenpath[i]);
}
}else{
printf("Distance = %d: ",dis[to]);
printf("%d",from);
for(int i=lenpath.size()-;i>=;i--)
printf(" -> %d",lenpath[i]);
printf("\n");
printf("Time = %d: ",tim[to]);
printf("%d",from);
for(int i=tmpath.size()-;i>=;i--)
printf(" -> %d",tmpath[i]);
}
return ;
}
//学习了
1.在迪杰斯特拉中,用邻接矩阵来存储,比如边矩阵,先初始化为INF,然后再将输入的边权作为矩阵的存储元素就可以了。
//我一开始还想用邻接表存储图,直接用邻接矩阵存储边就可以了啊。。。
2.最终在dfs的时候,初始点是to,而不是from,因为存的是前驱啊!
3.在选出一个点进行遍历的时候u.一定要标记为1,已经访问过啊。。。
4.在dfs时,遍历的时候,直接for遍历前驱,先push进去,遍历完在弹出来就看可以pop_back了就可以。
PAT 1111 Online Map[Dijkstra][dfs]的更多相关文章
- 1018 Public Bike Management (30分) PAT甲级真题 dijkstra + dfs
前言: 本题是我在浏览了柳神的代码后,记下的一次半转载式笔记,不经感叹柳神的强大orz,这里给出柳神的题解地址:https://blog.csdn.net/liuchuo/article/detail ...
- PAT 1111 Online Map
Input our current position and a destination, an online map can recommend several paths. Now your jo ...
- PAT甲级——1111 Online Map (单源最短路经的Dijkstra算法、priority_queue的使用)
本文章同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/90041078 1111 Online Map (30 分) ...
- PAT甲级1111. Online Map
PAT甲级1111. Online Map 题意: 输入我们当前的位置和目的地,一个在线地图可以推荐几条路径.现在你的工作是向你的用户推荐两条路径:一条是最短的,另一条是最快的.确保任何请求存在路径. ...
- 1111 Online Map (30 分)
1111. Online Map (30)Input our current position and a destination, an online map can recommend sever ...
- PAT-1030 Travel Plan (30 分) 最短路最小边权 堆优化dijkstra+DFS
PAT 1030 最短路最小边权 堆优化dijkstra+DFS 1030 Travel Plan (30 分) A traveler's map gives the distances betwee ...
- 1111 Online Map (30 分)
1111 Online Map (30 分) Input our current position and a destination, an online map can recommend sev ...
- 天梯赛练习 L3-011 直捣黄龙 (30分) dijkstra + dfs
题目分析: 本题我有两种思路,一种是只依靠dijkstra算法,在dijkstra部分直接判断所有的情况,以局部最优解得到全局最优解,另一种是dijkstra + dfs,先计算出最短距离以及每个点的 ...
- 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治
题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...
随机推荐
- VS 清除编译产生的临时文件、文件夹
VS编译过程中会产生一些临时文件,通过以下脚本可清除 @echo off for /r %%i in (*.sdf,*.ncb,*.suo,*.exp,*.user,*.aps,*.idb,*.dep ...
- 通过phoenix创建hbase表失败,创建语句卡住,hbase-hmaster报错:exception=org.apache.hadoop.hbase.TableExistsException: SYNC_BUSINESS_INFO_BYDAY_EFFECT
问题描述: 前几天一个同事来说,通过phoenix创建表失败了,一直报表存在的错误,删除也报错,然后就针对这个问题找下解决方案. 问题分析: 1.通过phoenix创建表,一直卡住不动了.创建语句如下 ...
- SDUT -refresh的停车场(栈和队列)
题目描写叙述 refresh近期发了一笔横財,开了一家停车场.因为土地有限,停车场内停车数量有限,可是要求进停车场的车辆过多. 当停车场满时,要进入的车辆会进入便道等待.最先进入便道的车辆会优先 进 ...
- day15<集合框架>
集合框架(对象数组的概述和使用) 集合框架(集合的由来及集合继承体系图) 集合框架(Collection集合的基本功能测试) 集合框架(集合的遍历之集合转数组遍历) 集合框架(Collection集合 ...
- STM32学习之路之入门篇
2006年ARM公司推出了基于ARMV7架构的cortex系列的标准体系结构,以满足各种技术得不同性能要求,包含了A,R,M三个分工明确的系列 其中A系列面向复杂的尖端应用程序,用于运行开放式的复杂操 ...
- 如何禁止审查元素扒代码(F12)
查看网页源码无非是三种,右键,ctrl+shift+i,f12我们只要禁止即可,代码如下 window.onload=function(){ document.onkeydown=function() ...
- 《C#高级编程》学习笔记------抗变和协变
1.协变和抗变 在.NET 4之前,泛型接口是不变的..NET 4通过协变和抗变为泛型接口和泛型委托添加了一个重要的扩展.协变和抗变指对参数和返回值的类型进行转换.例如,可以给一个需要Shape参数的 ...
- Windows系统调用架构分析—也谈KiFastCallEntry函数地址的获取
为什么要写这篇文章 1. 因为最近在学习<软件调试>这本书,看到书中的某个调试历程中讲了Windows的系统调用的实现机制,其中讲到了从Ring3跳转到Ring0之后直接进入了K ...
- 【Android N 7.1.1】 ActivityManagerService 获取cpu状态
void updateCpuStatsNow() { synchronized (mProcessCpuTracker) { mProcessCpuMutexFree.set(false); fina ...
- 【BZOJ3772】精神污染 DFS序+主席树
[BZOJ3772]精神污染 Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是 ...