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& ...
随机推荐
- LINQ---查询变量
LINQ查询可以返回两种类型的结果----枚举和标量(scalar)的单一值 namespace ConsoleApplication46 { class Program { static void ...
- PHP7 源码整体框架
一.PHP7语言执行原理 常用的高级语言有很多种,根据运行的方式不同,大体分为两种:编译型语言和解释型语言. 编译是指在应用源程序执行之前,就将程序源代码“翻译”成汇编语言,然后进一步根据软硬件环境编 ...
- LVS负载均衡基本原理
负载均衡基本原理与lvs 基本介绍 1.1 负载均衡的由来 在业务初期,我们一般会先使用单台服务器对外提供服务.随着业务流量越来越大,单台服务器无论如何优化,无论采用多好的硬件,总会有性能天花板,当单 ...
- vs2010编译C++ 栈的使用
// CTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include &l ...
- Microsoft Windows 实用程序 Sysinternals Utilities Index
最新页面时间:2017年5月16日 Sysinternals被MS收购--windows internals共近70多个工具集 Sysinternals套件 整套Sysinternals Utilit ...
- Unity Reflection Probe使用入门
贴官方API的说法: 反射探头: 一个反射探头很像一个相机,捕获了周围所有方向的球形视图.然后将捕获的图像存储为Cubemap,可由具有反射材料的对象使用.在给定场景中可以使用多个反射探测器,可以将对 ...
- POJ - 3468 A Simple Problem with Integers (线段树区间更新---间接修改)
题意:区间add,区间求和. #include<cstdio> #include<cstring> #include<cstdlib> #include<cc ...
- 官网英文版学习——RabbitMQ学习笔记(五)Publish/Subscribe
发布/订阅模式:把一个消息发送给多个消费者. 前几篇文章的思想是,我们好像看到了生产者将消息直接发送给queue,然后消费者也从queue中进行消费.其实并非如此,RabbitMQ中的消息传递模型的核 ...
- mapper语句的一些问题,union连表查询和mapper中根据条件不同采用不同语句的查询问题
根据业务要求,不同表查出来的内容天需要一起展示出来,并且还有分页之类的,不同表查询字段也不完全相同,这样就有一个问题,不同表如何接合在一起,不同字段怎么办? 这个问题就需要用到union联合查询,并将 ...
- 解决CSS背景模糊
.banner{ background:url(banner.jpg); -moz-background-size:100% 100%; background-size:100% 100%; }