shuoj-小6爱夜跑--Floyd记录多个最短路径

2023-12-22 17:32

本文主要是介绍shuoj-小6爱夜跑--Floyd记录多个最短路径,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

自从小6学了最短路算法之后,就成了一个不折不扣的最短路理论拥护者,每次在校园里夜跑的时候,只要确定好起点和终点他就能快速算出最短的路径。然而小6却没有走过每一条路,只是对这些路径长度做了一个粗略估计,于是每条路就有了估计值与实际值的差距。小6想要知道从起点到终点,按照其中任意一条预估的最短路径跑,实际最长可能需要走过的路程。(因为同一长度的最短路可能有多个)

Input

多组输入,第一行是一个整数T,表示输入数据的组数(T≤20)。

接下来有T组数据,每组数据的第一行是四个整数N、M、S、E,分别代表图中的顶点数、边数、起点编号和终点编号。

(2N100, 1M1000, 1S,TN, ST)

之后的M行每行有四个整数u, v, a, b,代表图中编号为u的点到编号为v的点有一条双向边。

每条边有两个值a、b分别代表这条边的估计长度与实际长度。

(1u,vN, 1a,b1000, u ≠ v)

数据保证两个顶点间至多只有一条双向边相连,起点与终点间必定存在通路。

Output

对于每组输入,输出一行两个整数并换行,表示小6估算出的最短路长度以及实际最长可能需要走过的路程,两个整数间有一个空格。

Sample Input

22 1 1 21 2 3 43 3 1 31 2 2 31 3 3 42 3 1 2

Sample Output

3 43 5


题意::有一个图,图有两层,通过第一层的数据求所有的最短路。然后用第二层的权值计算第一层求得的最短路的最大权值。
刚开始看这道题就想到了记录路径的方式,但是究竟如何把多个路径记录下来呢?这里的确遇到了问题。在这里给出了用Floyd记录多重路径的 方法。


题解::

1)假设c【A】【B】数组中存放A,B两点的最短路,我们知道如果在c【A】【B】 == c【A】【C】+c【C】【B】,那么(A->C->B)也是一条最短路。所以我们可以用二维的vector记录中间节点C,既path【A】【B】.push_back(C)。

2)Floyd算法更新节点是在c【A】【B】 > c【A】【C】+c【C】【B】的时候。同样的如果满足该条件,那么path【A】【B】中存放的都将不是最短路,要进行clear()操作。

3)我们知道如果从A点到B点有N种最短路径,B点到C点有M种最短路径,那么从A经过B到C共有N*M种最短路径。(计算最短路有多少条)。

当把最短路都记录下来后还有一个问题,如何根据最短路求题中要求的最长路。

1)如果path【A】【B】为 空,那最长路肯定是d【A】【B】
2)如果path【A】【B】不为空,
        1)假如有一条最短路A->C->B就分别求A C之间最长路,和B C之间的最长路。分别放入d【A】【C】,d【C】【B】。
2)比较d【A】【B】与d【A】【C】+d【C】【B】的大小。既d【A】【B】 = d【A】【B】>d【A】【C】+d【C】【B】? d【A】【B】:d【A】【C】+d【C】 【B】(C可能有多个。)
(用递归实现)


思路在经过细分析后也不是很难,哈哈哈。
代码如下:


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
vector<ll> path[120][120];ll c[120][120];
ll d[120][120];
ll max_load(int x,int y){if(path[x][y].empty())return d[x][y];for(int i = 0;i<path[x][y].size();i++){ll ans = path[x][y][i];return max(d[x][y],max_load(ans,y)+max_load(x,ans));}
}
int main(){int T;cin>>T;while(T--){for(int i = 0;i<120;i++)for(int j = 0;j<120;j++)path[i][j].clear();int m,n,s,e;cin>>n>>m>>s>>e;int u,v,a,b;for(int i = 0;i<n;i++)for(int j = 0;j<n;j++)c[i][j] = 2000;for(int i = 0;i<n;i++)c[i][i] = 0;for(int i = 0;i<m;i++){cin>>u>>v>>a>>b;u--;v--;c[u][v] = a;c[v][u] = a;d[u][v] = b;d[v][u] = b;}for (int k =0 ; k< n; k++){for (int i = 0; i< n; i++){for (int j = 0; j< n; j++)if (c[i][j] > c[i][k] + c[k][j]){c[i][j] = c[i][k]+c[k][j];path[i][j].clear();path[i][j].push_back(k);}else if (c[i][j] == c[i][k] + c[k][j] && k!= i &&k !=j)path[i][j].push_back(k);}}cout<<c[s-1][e-1]<<" ";cout<<max_load(s-1,e-1)<<endl;}return 0;
}
谢谢!











这篇关于shuoj-小6爱夜跑--Floyd记录多个最短路径的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/524836

相关文章

hdu2544(单源最短路径)

模板题: //题意:求1到n的最短路径,模板题#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#i

uva 10099(floyd变式)

题意: 有一个导游要带着一群旅客从一个城市到达另一个城市,每个城市之间有最大的旅客流量限制。 问最少几趟能将这些旅客从一个城市搞到另一个城市。 解析: 用floyd找出最小流量中的最大边,然后次数就是   ceil(总人数 / 最大承载量 - 1),-1的意思是导游每次也要在车上。 ps.老司机哭晕在厕所 代码: #include <iostream>#includ

uva 10048(floyd变式)

题意: 求两个点之间经过的路径中最大噪声最小的值。 解析: floyd的变式,每次取g[i][k] g[k][j]中的大边与当前边g[i][j]比较,取小。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#includ

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

【408DS算法题】039进阶-判断图中路径是否存在

Index 题目分析实现总结 题目 对于给定的图G,设计函数实现判断G中是否含有从start结点到stop结点的路径。 分析实现 对于图的路径的存在性判断,有两种做法:(本文的实现均基于邻接矩阵存储方式的图) 1.图的BFS BFS的思路相对比较直观——从起始结点出发进行层次遍历,遍历过程中遇到结点i就表示存在路径start->i,故只需判断每个结点i是否就是stop

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

图的最短路径算法——《啊哈!算法》

图的实现方式 邻接矩阵法 int[][] map;// 图的邻接矩阵存储法map = new int[5][5];map[0] = new int[] {0, 1, 2, 3, 4};map[1] = new int[] {1, 0, 2, 6, 4};map[2] = new int[] {2, 999, 0, 3, 999};map[3] = new int[] {3, 7