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出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...
随机推荐
- ubuntu zip解压
您好,zip xx.zip压缩,unzip xx.zip 解压,tar zcvf xx.tar.gz压缩tar zxvf xx.tar.gz解压
- TCP/IP协议族-----24、网络管理(SNMP)
- U3D关于message的使用
Message相关有3条指令: SendMessage ("函数名",参数,SendMessageOptions) //GameObject自身的Script BroadcastM ...
- 关于微信的jsdk的若干亲身实践之小结
前言: 业务来源:自主研发的手机app软件有分享文章到微信或者QQ以及微博的功能,而在微信中再次点击分享按钮的时候,情况就出现的不可把控了: 文章显示的缩略图不能正常显示:文章的简介不能显示……而我们 ...
- 原生JS,实现图片可拖拽,并且移动四个角和四条变能够自由变换图片大小
网上搜的资料,源码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- Linux 启动文件、设置环境变量的位置
系统级启动文件 ==================================== 1./etc/rc 主启动文件,不要修改它 2./etc/rc.conf 决定启动哪些系统自带的守护进程 ...
- Java 去除List列表中的重复项
/** * Remove list duplicate item * * @param srcList * @return */ private static ArrayList<Resolve ...
- ubuntu android studio kvm
Android studio 启动模拟器失败: Cannot launch AVD in emulator.Output:emulator: ERROR: x86 emulation currentl ...
- WEB安全第二篇--用文件搞定服务器:任意文件上传、文件包含与任意目录文件遍历
零.前言 最近做专心web安全有一段时间了,但是目测后面的活会有些复杂,涉及到更多的中间件.底层安全.漏洞研究与安全建设等越来越复杂的东东,所以在这里想写一个系列关于web安全基础以及一些讨巧的pay ...
- Oracle入门笔记 ——启动进阶
1.2 进阶内容: 两个概念:SCN 和 检查点 1.SCN的定义: system change member ,系统改变号,是数据库中非常重要的一个数据结构. SCN 用以标示数据 ...