博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浪里个浪 FZU - 2261 (多源最短路问题)
阅读量:4046 次
发布时间:2019-05-25

本文共 2362 字,大约阅读时间需要 7 分钟。

TonyY是一个喜欢到处浪的男人,他的梦想是带着兰兰姐姐浪遍天朝的各个角落,不过在此之前,他需要做好规划。

现在他的手上有一份天朝地图,上面有n个城市,m条交通路径,每条交通路径都是单行道。他已经预先规划好了一些点作为旅游的起点和终点,他想选择其中一个起点和一个终点,并找出从起点到终点的一条路线亲身体验浪的过程。但是他时间有限,所以想选择耗时最小的,你能告诉他最小的耗时是多少吗?

Input

包含多组测试数据。

输入第一行包括两个整数n和m,表示有n个地点,m条可行路径。点的编号为1 - n。

接下来m行每行包括三个整数i, j, cost,表示从地点i到地点j需要耗时cost。

接下来一行第一个数为S,表示可能的起点数,之后S个数,表示可能的起点。

接下来一行第一个数为E,表示可能的终点数,之后E个数,表示可能的终点。

0<S, E≤n≤100000,0<m≤100000,0<cost≤100。

Output

输出他需要的最短耗时。

Sample Input

4 41 3 11 4 22 3 32 4 42 1 22 3 4

Sample Output

1

题意: 

这个题就是一个多源最短路的问题。多源最短路的问题可以转换为单源最短路:将所有的起点全部通过一个自己添加的初始点(比如 ‘0’点) 且0点到所有的起点的距离全部为0,然后再添加一个最终点n+1(默认有n个地点),来让所有的可以到达的终点到最终点n+1的距离全部为0,然后找从新起点‘0’到最终点‘n+1’的最短路。

这个题可以使用dijkstra和spfa,但是使用普通的dijkstra的话由于题目中给出的个数都比较大,所以会超时超内存,所以要用堆优化的dijkstra。

(堆优化的dijkstra与spfa是类似的,堆优化的dijkstra用了堆,每次都找出最短的路径来松弛每个边,一下子就可以松弛到最短路径;而spfa是将所有的点都放入队列,顺序来进行松弛,逐渐的趋近最短路)

堆优化的dijkstra算法:

#include
#include
#include
#include
#include
#include
using namespace std;const int maxn=1e5+10;const int inf=0x3f3f3f3f;struct Edge{ int to; int val; bool operator < (const Edge& a)const //重载运算符 ‘<’,变为最小堆 { return val>a.val; } Edge(int a,int b):to(a),val(b){} Edge(){}};int dis[maxn]; //存放起点到达每个点的最短路int vis[maxn];int n,m;vector
path[maxn];void dijkstra(){ memset(vis,0,sizeof(vis)); memset(dis,inf,sizeof(dis)); priority_queue
queue; dis[0]=0; queue.push(Edge(0,0)); while(!queue.empty()) { Edge tmp=queue.top(); queue.pop(); int a=tmp.to; if(vis[a]==1)continue; vis[a]=1; for(int i=0;i
dis[a]+path[a][i].val) { dis[b]=dis[a]+path[a][i].val; Edge e=Edge(b,dis[b]); queue.push(e); } } }}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { for(int i=0;i<=n;i++) path[i].clear(); for(int i=0;i

spfa算法:

#include
#include
#include
#include
#include
#include
using namespace std;const int maxn=1e5+10;const int inf=0x3f3f3f3f;struct Edge{ int to; int val; Edge(int a,int b):to(a),val(b){} Edge(){}};int dis[maxn];int vis[maxn];int n,m;vector
path[maxn];void dijkstra(){ memset(vis,0,sizeof(vis)); for(int i=0;i<=n+1;i++) dis[i]=inf; dis[0]=0; queue
q; vis[0]=1; q.push(0); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0;i
dis[x]+val) dis[to]=dis[x]+val; if(!vis[to]) { q.push(to); vis[to]=1; } } }}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { for(int i=0;i

 

转载地址:http://mizci.baihongyu.com/

你可能感兴趣的文章
socket编程中select的使用
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
No.147 - LeetCode1108
查看>>
No.174 - LeetCode1305 - 合并两个搜索树
查看>>
No.175 - LeetCode1306
查看>>
No.176 - LeetCode1309
查看>>
No.182 - LeetCode1325 - C指针的魅力
查看>>
mysql:sql alter database修改数据库字符集
查看>>
mysql:sql truncate (清除表数据)
查看>>
yuv to rgb 转换失败呀。天呀。谁来帮帮我呀。
查看>>
yuv420 format
查看>>
yuv420 还原为RGB图像
查看>>
LED恒流驱动芯片
查看>>
驱动TFT要SDRAM做为显示缓存
查看>>