题目

A traveler’s map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (<=500) is the number of cities (and hence the cities are numbered from 0 to N-1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

City1 City2 Distance Cost

where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input

4 5 0 3

0 1 1 20

1 3 2 30

0 3 4 10

0 2 2 20

2 3 1 20

Sample Output

0 2 3 3 40

题意

地图上显示了城市间高速公路的距离和费用,计算起点到终点距离最短的路线,如果有多条距离最短路线,取费用最低的最短路线

题目分析

已知图的顶点、边、两种边权(距离和费用),求单源带权最短路径,要求距离最短,若距离最短路径有多条,取费用最低的最短路径

解题思路

  1. 存储图信息

    邻接矩阵

    邻接表
  2. 求最短路径

    2.1 dijkstra算法,求距离最短路径的同时,求出距离最短并且费用最少的最短路径

    2.2 dijkstra算法,求出所有距离最短路径并存储,dfs遍历所有距离最短路径,求出距离最短并且费用最少的最短路径

int gw[maxn][maxn] //记录边权-距离

int ct[maxn][maxn] //记录边权-费用

int dist[maxn] //dijkstra记录从源点到其他顶点的最短距离

int path[maxn] //dijskstra记录最短距离路径

int act[maxn] //dijskstra记录从源点到其他顶点的最少费用

int col[maxn] //标记已收集到最短路径中的顶点

  1. 打印最短路径

    3.1 利用栈(先进后出)

    3.2 dfs

Code

Code 01(邻接矩阵 dijskstra求距离最短费用最少路径)

#include <iostream>
#include <stack>
using namespace std;
const int maxn=510;
const int INF=0x7fffffff;
int n,s,d,gw[maxn][maxn],ct[maxn][maxn];// gw边权-距离;ct边权-费用
int dist[maxn],path[maxn],act[maxn]; //act 总边权-总费用;
int col[maxn];//col 已收集到最短路径标记
/* dijkstra 求单源带权最短路径 */
void dijkstra(int x) {
/*1 初始化*/
fill(dist,dist+maxn,INF);
fill(act,act+maxn,INF);
fill(path,path+maxn,-1);
dist[x]=0;
act[x]=0;
for(int j=0; j<n; j++) {
/*2 查找最小dist*/
int mind=INF,min=-1;
for(int i=0; i<n; i++) {
if(col[i]==0 && dist[i]<mind) {
mind=dist[i];
min=i;
}
}
if(min==-1||min==d)break;
col[min]=1;
/*3 最小路径*/
for(int i=0; i<n; i++) {
if(gw[min][i]==0||col[i]==1)continue;
if(dist[i]>dist[min]+gw[min][i]) {
dist[i]=dist[min]+gw[min][i];
path[i]=min;
act[i]=act[min]+ct[min][i];
} else if(dist[i]==dist[min]+gw[min][i]&&act[i]>act[min]+ct[min][i]) {
path[i]=min;
act[i]=act[min]+ct[min][i];
}
}
}
}
/* 打印最短路径 方法一*/
void dfs(int y) {
if(y==-1)return;
dfs(path[y]);
printf("%d ",y);
}
/* 打印最短路径 方法二*/
//void ppt(int y) {
// stack<int> sk;
// int p=y;
// while(p!=-1) {
// sk.push(p);
// p=path[p];
// }
// while(!sk.empty()) {
// printf("%d ",sk.top());
// sk.pop();
// }
//}
int main(int argc,char * argv[]) {
int m,a,b;
scanf("%d %d %d %d",&n,&m,&s,&d);
for(int i=0; i<m; i++) {
scanf("%d %d",&a,&b);
scanf("%d",&gw[a][b]);
scanf("%d",&ct[a][b]);
gw[b][a]=gw[a][b];
ct[b][a]=ct[a][b];
}
dijkstra(s);
dfs(d);
// ppt(d);
printf("%d %d",dist[d],act[d]);
return 0;
}

Code 02(邻接矩阵 dijkstra求最短距离路径 dfs求最少费用路径)

#include <iostream>
#include <vector>
using namespace std;
const int INF=0x7fffffff;
const int maxn = 510;
int gw[maxn][maxn],ct[maxn][maxn];
int dist[maxn],path[maxn],act[maxn],col[maxn];
int n,m,s,d,minct=INF;
vector<int> pre[maxn],tempth,fp;
void dijkstra(int v) {
fill(dist,dist+maxn,INF);
fill(path,path+maxn,-1);
fill(act,act+maxn,INF);
dist[v]=0;
act[v]=0;
for(int i=0; i<n; i++) {
int min=-1,mind=INF;
for(int j=0; j<n; j++) {
if(col[j]==0&&dist[j]<mind) {
mind=dist[j];
min=j;
}
}
if(min==-1||min==d)break;
col[min]=1;
for(int j=0; j<n; j++) {
if(gw[min][j]==0||col[j]==1)continue;
if(dist[min]+gw[min][j]<dist[j]) {
dist[j]=dist[min]+gw[min][j];
path[j]=min;
pre[j].clear();
pre[j].push_back(min);
} else if(dist[min]+gw[min][j]==dist[j]) {
path[j]=min;
pre[j].push_back(min);
}
}
}
}
void dfs(int u) {
if(u==s) {
tempth.push_back(u);
int tempct=0;
for(int i=tempth.size()-1; i>=1; i--) {
tempct+=ct[tempth[i]][tempth[i-1]];
}
if(minct>tempct) {
minct=tempct;
fp = tempth;
}
tempth.pop_back();
return;
}
tempth.push_back(u);
for(int i=0; i<pre[u].size(); i++) {
dfs(pre[u][i]);
}
tempth.pop_back();
}
int main(int argc,char * argv[]) {
scanf("%d %d %d %d",&n,&m,&s,&d);
int a,b;
for(int i=0; i<m; i++) {
scanf("%d %d",&a,&b);
scanf("%d",&gw[a][b]);
scanf("%d",&ct[a][b]);
gw[b][a]=gw[a][b];
ct[b][a]=ct[a][b];
}
dijkstra(s);
dfs(d);
for(int i=fp.size()-1; i>=0; i--) {
printf("%d ",fp[i]);
}
printf("%d %d",dist[d],minct);
return 0;
}

Code 03(邻接表 dijskstra求距离最短费用最少路径)

#include <iostream>
#include <vector>
using namespace std;
const int maxn=510;
const int INF=0x7fffffff;
int n,s,d;// gw边权-距离;ct边权-费用
int dist[maxn],path[maxn],act[maxn]; //act 总边权-总费用;
int col[maxn];//col 已收集到最短路径标记
struct node{
int v;
int sw; //距离
int cw; //费用
};
vector<node> g[maxn];
/* dijkstra 求单源带权最短路径 */
void dijkstra(int x) {
/*1 初始化*/
fill(dist,dist+maxn,INF);
fill(act,act+maxn,INF);
fill(path,path+maxn,-1);
dist[x]=0;
act[x]=0;
for(int j=0; j<n; j++) {
/*2 查找最小dist*/
int mind=INF,min=-1;
for(int i=0; i<n; i++) {
if(col[i]==0 && dist[i]<mind) {
mind=dist[i];
min=i;
}
}
if(min==-1||min==d)break;
col[min]=1;
/*3 最小路径*/
for(int i=0; i<g[min].size(); i++) {
node u=g[min][i];
if(col[u.v]==1)continue;
if(dist[u.v]>dist[min]+u.sw) {
dist[u.v]=dist[min]+u.sw;
path[u.v]=min;
act[u.v]=act[min]+u.cw;
} else if(dist[u.v]==dist[min]+u.sw&&act[u.v]>act[min]+u.cw) {
path[u.v]=min;
act[u.v]=act[min]+u.cw;
}
}
}
}
/* 打印最短路径 方法一*/
void dfs(int y) {
if(y==-1)return;
dfs(path[y]);
printf("%d ",y);
}
/* 打印最短路径 方法二*/
//void ppt(int y) {
// stack<int> sk;
// int p=y;
// while(p!=-1) {
// sk.push(p);
// p=path[p];
// }
// while(!sk.empty()) {
// printf("%d ",sk.top());
// sk.pop();
// }
//}
int main(int argc,char * argv[]) {
int m,a,b,sw,cw;
scanf("%d %d %d %d",&n,&m,&s,&d);
for(int i=0; i<m; i++) {
scanf("%d %d",&a,&b);
scanf("%d",&sw);
scanf("%d",&cw);
g[a].push_back({b,sw,cw});
g[b].push_back({a,sw,cw});
}
dijkstra(s);
dfs(d);
// ppt(d);
printf("%d %d",dist[d],act[d]);
return 0;
}

Code 04 (邻接表 dijkstra求最短距离路径 dfs求最少费用路径)

因为该求解方法,dfs中需要根据顶点a,b寻找边,若使用邻接表,需要遍历g[a]的所有有关联的顶点,找到b的node

非要使用邻接表可以使用map<int,node> g[maxn];

PAT Advanced 1030 Travel Plan (30) [Dijkstra算法 + DFS,最短路径,边权]的更多相关文章

  1. PAT Advanced 1111 Online Map (30) [Dijkstra算法 + DFS]

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

  2. PAT 甲级 1030 Travel Plan (30 分)(dijstra,较简单,但要注意是从0到n-1)

    1030 Travel Plan (30 分)   A traveler's map gives the distances between cities along the highways, to ...

  3. PAT A 1030. Travel Plan (30)【最短路径】

    https://www.patest.cn/contests/pat-a-practise/1030 找最短路,如果有多条找最小消耗的,相当于找两次最短路,可以直接dfs,数据小不会超时. #incl ...

  4. PAT Advanced 1072 Gas Station (30) [Dijkstra算法]

    题目 A gas station has to be built at such a location that the minimum distance between the station an ...

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

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

  6. [图算法] 1030. Travel Plan (30)

    1030. Travel Plan (30) A traveler's map gives the distances between cities along the highways, toget ...

  7. PAT Advanced 1018 Public Bike Management (30) [Dijkstra算法 + DFS]

    题目 There is a public bike service in Hangzhou City which provides great convenience to the tourists ...

  8. 1030 Travel Plan (30)(30 分)

    A traveler's map gives the distances between cities along the highways, together with the cost of ea ...

  9. PAT (Advanced Level) 1030. Travel Plan (30)

    先处理出最短路上的边.变成一个DAG,然后在DAG上进行DFS. #include<iostream> #include<cstring> #include<cmath& ...

随机推荐

  1. Python测试进阶——(3)编写Python程序监控计算机的服务是否正常运行

    用python写了个简单的监控进程的脚本,当发现进程消失的时候,立即调用服务,开启服务. 脚本的工作原理是这样的:脚本读取配置文件,读取预先配置好的调用系统服务的路径和所要监控的服务在进程管理器中的进 ...

  2. Linux 只复制目录,不复制目录下数据文件

    [root@yoon u02]# mkdir yoon [root@yoon u02]# mkdir hank [root@yoon yoon]# mkdir -p 1/data [root@yoon ...

  3. 强大的promise

    这个玩意叫做普罗米修斯,希腊神话的盗火英雄 promise只用来包装异步函数,同步的会搞乱执行顺序,生产BUG // 如何使用 function pro(){ return new Promise(f ...

  4. git 提取某次提交所修改的代码

    git 提取某次提交所修改的代码 应用场景 把分支A的某个功能抽到分支B中. 首先切换到分支B, 然后进行遴选(git cherry-pick). 如果没有冲突, 会自动合并然后使用原信息提交. 如果 ...

  5. C# 控件缩写规范

    标准控件缩写规范 类 型 前 缀 示 例 Adrotator adrt adrtTopAd BulletedList blst blstCity Button btn btnSubmit Calend ...

  6. pyhton pandas数据分析基础入门(一文看懂pandas)

    //2019.07.17 pyhton中pandas数据分析基础入门(一文看懂pandas), 教你迅速入门pandas数据分析模块(后面附有入门完整代码,可以直接拷贝运行,含有详细的代码注释,可以轻 ...

  7. Linux学习-预习第五六七章节关于用户权限管理以及磁盘文件系统

  8. 使用Ubuntu系统管理包工具(apt)部署Zabbix企业级监控系统

    使用Ubuntu系统管理包工具(apt)部署Zabbix企业级监控系统  作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Ubuntu系统部署笔记:https://www.cnblo ...

  9. HihoCoder第十二周:刷油漆

    #1055 : 刷油漆 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho有着一棵灰常好玩的树玩具!这棵树玩具是由N个小球和N-1根木棍拼凑而成,这N个小球 ...

  10. tomcat中war 和 war exploded的区别

    war和war exploded的区别(转载) 在使用idea开发项目的时候,部署Tomcat的时候通常会出现下边的情况: 是选择war还是war exploded这里首先看一下他们两个的区别: wa ...