题目

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. ubuntu 环境下pycharm的 安装与激活教程

    1. 基本安装: 1.1 打开Ubuntu的应用市场,并在搜索栏搜索pycharm,结果如下图所示 1.2 选择pro版本进行安装,结果如下图所示: 1.3打开安装后的pycharm,如果出现下图所示 ...

  2. HTML学习第五天

    HTML学习第五天 今天学HTML的实体.背景.布局 HTML布局的标签基本被淘汰frameset就被淘汰了,只有iframe依然存活,但是iframe可以被CSS给代替.下面就是一个练习的程序 &l ...

  3. STM32F103 USB虚拟串口 驱动例程移植

    1)驱动下载及安装.目前ST公司支持WIN7版本号为:VCP_V1.3.1_Setup.exe (在官网上搜索stsw-stm32102即是了):先安装驱动后再插入USB不然安装不成功. 2)固件下载 ...

  4. login SMTP send mail error : Unable to read data from the transport connection: net_io_connectionclosed

    client.Credentials = new NetworkCredential(sSMTPuser, sSMTPpass); client.Credentials = new NetworkCr ...

  5. net Core3.1 Swagger加JWT权限

    1.Swagger中开启JWT服务 #region swagger services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new ...

  6. Nifi简介及核心概念整理

    简介 Apache NiFi 是一个易于使用.功能强大而且可靠的数据拉取.数据处理和分发系统,用于自动化管理系统间的数据流. 它支持高度可配置的指示图的数据路由.转换和系统中介逻辑,支持从多种数据源动 ...

  7. 解决fedora28桌面图标问题

    正文 在fedora28中默认是没有桌面图标的,对于那些习惯使用桌面的图标的人来说使用有点不适应. 替代方法是: 下载nemo,在终端内输入sudo dnf install nemo 创建~/.con ...

  8. ACM-小偷的背包

    题目描述:小偷的背包   设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,...,wn.问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S.如果有满足条 ...

  9. setup factory 设置自启动

    Registry.SetValue(HKEY_LOCAL_MACHINE, "Software//Microsoft//Windows//CurrentVersion//Run", ...

  10. 【Linux】linux内核学习

    linux内核获取 官网: https://www.kernel.org/ Linux操作系统的核心是模块化,可以使用lsmod命令查看内核模块,下面展示已载入系统的模块: [root@172.16. ...