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出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...
随机推荐
- mysqldump工具,工作的本质是什么呢?(dump表的时候,是否会产生drop表的语句)
需求描述: 今天在看mysqldump工具的使用过程,发现一个同事,是这样写的mysqldump命令 mysqldump -uroot -pmysql employees titles | mysql ...
- linux用户态定时器的使用---19
原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/ linux操作系统为每一个进程提供了3个内部计时器. ITIMER_REAL;ITIMER_VI ...
- 超全面的JavaWeb笔记day22<文件上传>
文件上传概述 1 文件上传的作用 例如网络硬盘!就是用来上传下载文件的. 在智联招聘上填写一个完整的简历还需要上传照片呢. 2 文件上传对页面的要求 上传文件的要求比较多,需要记一下: 1. 必须使用 ...
- Extjs不错的博客
http://www.cnblogs.com/fangsui/category/372751.html http://www.cnblogs.com/WangJinYang/tag/EXT.NET/ ...
- SQL集合运算:差集、交集、并集
1.差集( except ) select a from t_a except select a from t_b -- 也可写作: select a from t_a where a not in ...
- swift - 之TabBarController的用法
TabBarController的使用,下面记录两种写法,代码如下: TabBarItem系统自带图标样式(System)介绍: Custom:自定义方式,配合Selected Image来自定义图标 ...
- Android NDK开发-3-环境搭建
1.创建Android工程 2.打开android-ndk32-r10-windows-x86_64\android-ndk-r10\samples例子 3.打开hello-jni,拷贝java代码和 ...
- 第五篇:浅谈CPU 并行编程和 GPU 并行编程的区别
前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...
- 第四篇:GPU 并行编程的存储系统架构
前言 在用 CUDA 对 GPU 进行并行编程的过程中,除了需要对线程架构要有深刻的认识外,也需要对存储系统架构有深入的了解. 这两个部分是 GPU 编程中最为基础,也是最为重要的部分,需要花时间去理 ...
- 基于51的串行通讯原理及协议详解(uart)
串行与并行通讯方式并行:控制简单,传输速度快.线多,长距离成本较高且同时接受困难.串行:将数据字节分成一位一位的行驶在一条传输线上进行传输.如图: 同步与异步串行通讯方式同步串行通讯方式:同步通讯 ...