PAT Advanced 1030 Travel Plan (30) [Dijkstra算法 + DFS,最短路径,边权]
题目
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
题意
地图上显示了城市间高速公路的距离和费用,计算起点到终点距离最短的路线,如果有多条距离最短路线,取费用最低的最短路线
题目分析
已知图的顶点、边、两种边权(距离和费用),求单源带权最短路径,要求距离最短,若距离最短路径有多条,取费用最低的最短路径
解题思路
- 存储图信息
邻接矩阵
邻接表 - 求最短路径
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] //标记已收集到最短路径中的顶点
- 打印最短路径
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,最短路径,边权]的更多相关文章
- PAT Advanced 1111 Online Map (30) [Dijkstra算法 + DFS]
题目 Input our current position and a destination, an online map can recommend several paths. Now your ...
- 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 ...
- PAT A 1030. Travel Plan (30)【最短路径】
https://www.patest.cn/contests/pat-a-practise/1030 找最短路,如果有多条找最小消耗的,相当于找两次最短路,可以直接dfs,数据小不会超时. #incl ...
- 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 ...
- PAT-1030 Travel Plan (30 分) 最短路最小边权 堆优化dijkstra+DFS
PAT 1030 最短路最小边权 堆优化dijkstra+DFS 1030 Travel Plan (30 分) A traveler's map gives the distances betwee ...
- [图算法] 1030. Travel Plan (30)
1030. Travel Plan (30) A traveler's map gives the distances between cities along the highways, toget ...
- 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 ...
- 1030 Travel Plan (30)(30 分)
A traveler's map gives the distances between cities along the highways, together with the cost of ea ...
- PAT (Advanced Level) 1030. Travel Plan (30)
先处理出最短路上的边.变成一个DAG,然后在DAG上进行DFS. #include<iostream> #include<cstring> #include<cmath& ...
随机推荐
- Django创建完全独立的APP
我们之前已经完成了项目的结构搭建,但是,在Django当中,我们强调的一个重要概念是app,比如Django自带的admin就是一个成功的app典范,那么我们应该如果整理自己的项目结构,才能让我们的a ...
- HiBench成长笔记——(2) CentOS部署安装HiBench
安装Scala 使用spark-shell命令进入shell模式,查看spark版本和Scala版本: 下载Scala2.10.5 wget https://downloads.lightbend.c ...
- 清北学堂模拟赛2 T2 ball
题目大意: 多组数据,每组给定n,m,表示将n个小球放进m个箱子,每个小球均有两个箱子(可能相同)可放,求所有小球均放好的方案mod998244353的总数. 思路: 算是我和题解思路肥肠相近的一道题 ...
- IIS7/8 HTTP Error 500.19 错误 0x80070021 错误代码:0x8007000d
nopCommerce versions 4.20 的安装环境是 dotnet-hosting-2.2.0-win.exe .net core项目iis10上出现 HTTP 错误 500.19,错误代 ...
- Linux间传输文件 scp
scp scp使用ssh来传输数据,使用相同的认证方式,所以配置好ssh后,根据用户名和密码来读写远程文件.基本命令如下,输完命令,回车,输入远程用户对应的密码: 从本机复制到远程: 文件:scp F ...
- NO8 find结合sed查找替换企业案例多方法精讲&命令总结!
·sed #替换 eg: sed 'sed 's#已有的内容#更改的内容#g' oldboy.txt s 代表替换,g代表全局,sg就是全局替换 ...
- 《ES6标准入门》(阮一峰)--10.对象的扩展
1.属性的简洁表示法 ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法.这样的书写更加简洁. const foo = 'bar'; const baz = {foo}; baz // ...
- CANmonitor我自己编写的程序
这个版本的程序, 上位机可以对电机的转速进行在线的设定,同时上位机接受电机控制器上报的母线电压,电机温度,控制器温度等. 在调试的过程中我遇见了一个问题,电机的转速的采样 . 根据协议:电机的转速为1 ...
- yum对于包和软件的安装、升级和卸载总结
在Centos下yum的安装.升级和卸载 一.使用yum安装和卸载软件,有个前提是yum安装的软件包都是rpm格式的.安装的命令是,yum install ~,yum会查询数据库,有无这一软件包,如果 ...
- 基于共享内存、信号、命名管道和Select模型实现聊天窗口
问题模型 A.B两个进程通过管道通信,A 进程每次接收到的数据通过共享内存传递给A1进程显示,同理,B进程每次接收到的数据通过共享内存传递给B1进程显示: 对于A.B 进程,采用ctrl+c(实际为S ...