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出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...
随机推荐
- html 页面模块的常用命名
头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目: ...
- CRC-16校验C#代码
[csharp] view plaincopyprint? using System; using System.Collections.Generic; using System.Text; usi ...
- Android - Style问题
转自:http://jingyan.baidu.com/article/c910274be7536acd361d2dca.html 转自:http://blog.sina.com.cn/s/blog_ ...
- json 数据分析
/* 健一健康头条 */ try { String url = "http://www.j1health.com/j1api.php/index/getJ1healthHotLists&qu ...
- 更改嵌入式Linux中开机画面----左上角小企鹅图标
一直想给嵌入式仪表加个开机LOGO,但是没有找到更换的方法.最近在网上收集了一些文章,整理一下一共自己参考.目前也还没有试过这种方法究竟是否可以.但察看Kernel源代码可以知道,Linux-2.6的 ...
- Android 使用CheckBox实现多选效果
CheckBox:复选框1.有两种状态: 选中状态(true),未选中状态(false)2.属性: android:id="@+id/checkbox" android:layou ...
- MYSQL系列之(一)
mysql简介 1.什么是数据库 ? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不 ...
- 《转》python学习--基础下
转自http://www.cnblogs.com/BeginMan/archive/2013/04/12/3016323.html 一.数字 在看<Python 核心编程>的时候,我就有点 ...
- web基础---->okhttp的使用
今天我们就讲一下okhttp的使用,具体的okhttp使用可以参见官方的文档. okhttp的使用 一.okhttp的下载安装 Download the latest JAR or grab via ...
- 【黑金ZYNQ7000系列原创视频教程】02.视频接口——hdmi编码输出实验
黑金论坛地址: http://www.heijin.org/forum.php?mod=viewthread&tid=36636&extra=page%3D1 爱奇艺地址: http: ...