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]的更多相关文章

  1. 1018 Public Bike Management (30分) PAT甲级真题 dijkstra + dfs

    前言: 本题是我在浏览了柳神的代码后,记下的一次半转载式笔记,不经感叹柳神的强大orz,这里给出柳神的题解地址:https://blog.csdn.net/liuchuo/article/detail ...

  2. PAT 1111 Online Map

    Input our current position and a destination, an online map can recommend several paths. Now your jo ...

  3. PAT甲级——1111 Online Map (单源最短路经的Dijkstra算法、priority_queue的使用)

    本文章同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/90041078   1111 Online Map (30 分) ...

  4. PAT甲级1111. Online Map

    PAT甲级1111. Online Map 题意: 输入我们当前的位置和目的地,一个在线地图可以推荐几条路径.现在你的工作是向你的用户推荐两条路径:一条是最短的,另一条是最快的.确保任何请求存在路径. ...

  5. 1111 Online Map (30 分)

    1111. Online Map (30)Input our current position and a destination, an online map can recommend sever ...

  6. PAT-1030 Travel Plan (30 分) 最短路最小边权 堆优化dijkstra+DFS

    PAT 1030 最短路最小边权 堆优化dijkstra+DFS 1030 Travel Plan (30 分) A traveler's map gives the distances betwee ...

  7. 1111 Online Map (30 分)

    1111 Online Map (30 分) Input our current position and a destination, an online map can recommend sev ...

  8. 天梯赛练习 L3-011 直捣黄龙 (30分) dijkstra + dfs

    题目分析: 本题我有两种思路,一种是只依靠dijkstra算法,在dijkstra部分直接判断所有的情况,以局部最优解得到全局最优解,另一种是dijkstra + dfs,先计算出最短距离以及每个点的 ...

  9. 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

    题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...

随机推荐

  1. 帝国CMS 列表模板list.var支持程序代码

    1.增加模板时list.var模板需要勾选“使用程序代码”选项.如图: 2.直接添加PHP代码,不需要加<?和?>程序开始和结束标记. 3.字段值数组变量为$r,对应的字段变量为$r[字段 ...

  2. ionic creator(ionic生成器)

    用来生成前端 html 还是挺方便的(接口数据另算),弄好就可以直接下载 https://creator.ionic.io/app/dashboard/projects

  3. leetcode -- permutation 总结

    leetcode上关于permutation有如下几题 Permutation Sequence Next Permutation Permutations Permutations II

  4. 告别C#,进入了下一个阶段的学习啦

    嘿嘿,今天我们结束了C#的基础的学习,开始啦第二个阶段的学习,就是对SQL Server的学习.今天又是一个周一,又是一个新的开始,感觉我们都是一周一周的计算,而不是每天到这个点就是告别了今天的生活啦 ...

  5. hive 客户端执行select count(1) from t_sz01

    yarn-site.xml配置错误 yarn.nodemanager.aux-services 中的-原先配置为_ 导致错误......

  6. JQuery自定义用户控件方法汇总

    首先必用 JQuery.fn.extend方法 使用方法: jQuery.fn.extend({}); 其次 相应控件配置参数设置: jQuery.fn.extend({ uploadPreview: ...

  7. ubuntu 14 root 账户 启用与ssh登录

    ubuntu 14.04 root用户登录 开启root帐号的方法: 为了启用root 帐号(也就是设置一个口令)使用: sudo passwd root 当你使用完毕后屏蔽root帐号使用: sud ...

  8. 银联支付-产品测试sdk使用流程

    准备工作: 到https://open.unionpay.com/ajweb/help/file/techFile?productId=66下载开发文档和sdk 下载之后进行解压将Java Versi ...

  9. 如何在Linux系统通过命令行生成随机文件

    版权声明:本文由胡恒威原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/86 来源:腾云阁 https://www.qclou ...

  10. Android 7.1 SystemUI--Multi-Window多窗口模式

    PhoneStatusBar.java private View.OnLongClickListener mRecentsLongClickListener = new View.OnLongClic ...