Folyd + 路径存储
一、Folyd 算法原理
- 如果 AB + AC < BC 那么, BC最短路就要经过 A。 在算法进行过程中,应该是
,B-A 有很多路径,B 代表这些路径权值之和,A-C也有很多路径,C是这些权值之和。那么我们找到一个 满足 AB + AC < BC 的时候更新权值数组,并且记录路径。
dist[i][j] = k 表示,从 I -- J 点的路径权值为 K
记录路径,就是将 C 点连接在 B A C 这样的路径后
二、简单容易理解版
核心代码:
//邻接矩阵保存点信息
int mapp[MAX_POINT][MAX_POINT];
//保存任意两点之间的最短路径上的节点
vector<int> trace_path[MAX_POINT][MAX_POINT]; void Folyd(int n) {
for (int k = ; k < n; k++)
for (int i = ; i < n; i++)
for (int j = ; j < n; j++)
if (mapp[i][j] > mapp[i][k] + mapp[k][j]) {
mapp[i][j] = mapp[i][k] + mapp[k][j];
trace_path[i][j].clear();
//放入 i---k 路径节点
for (int z = ; z < trace_path[i][k].size(); z++)
trace_path[i][j].push_back(trace_path[i][k][z]);
//放入 k---j 路径节点
for (int z = ; z < trace_path[k][j].size(); z++)
trace_path[i][j].push_back(trace_path[k][j][z]);
}
} void query(int from, int to) {
cout << "from " << from << " to " << to << " should cost " << mapp[from][to] <<"."<< endl;
cout << "trace_path: " ;
for (int i = ; i < trace_path[from][to].size(); i++)
cout<< trace_path[from][to][i] << " -> ";
cout << to << endl;
}
上述代码中:存在重复存储,效率极低
trace_path[i][j].clear();
//放入 i---k 路径节点
for (int z = ; z < trace_path[i][k].size(); z++)
trace_path[i][j].push_back(trace_path[i][k][z]);
//放入 k---j 路径节点
for (int z = ; z < trace_path[k][j].size(); z++)
trace_path[i][j].push_back(trace_path[k][j][z]);
优化代码:
由于上面代码每次都重复把点的信息都保存下来,因此,我们采用保存前驱几点的方式,最终通过回溯构建路径。
path[i][j] = k ; //表示 从 i---j 路径中, k 是 j 的直接前驱, 那么最短路径 1->5->4->3->6 有 paht[1][6] = 3; paht[1][3]= 4; paht[1][4] = 5; paht[1][5] =1 如此逆推不难得到 最短路径记录值
核心代码:
//邻接矩阵保存点信息
int mapp[MAX_POINT][MAX_POINT];
//path[i][j] = k ,表示从 i 到 j 最短路, k 邻接到j。
int path[MAX_POINT][MAX_POINT];
void Folyd(int n) {
//初始化路径数组
for (int i = ; i < n; i++)
for (int j = ; j < n; j++) {
if (mapp[i][j] - INF)
path[i][j] = i;
else
path[i][j] = NOTEXISTS;
} for (int k = ; k < n; k++)
for (int i = ; i < n; i++)
for (int j = ; j < n; j++)
if (mapp[i][j] > mapp[i][k] + mapp[k][j]) {
mapp[i][j] = mapp[i][k] + mapp[k][j];
//path[i][j] = k; //这种思路中,不能写成这样
path[i][j] = path[k][j];
}
} void print_path(int from, int to) {
if (path[from][to] != from)
print_path(from, path[from][to]);
cout << " -> " << to;
}
在更改权值的时候,即使记录下来当前点的前驱节点。 path[i][j] = path[k][j]; 切不可以写成,path[i][j] = k; 后者是另一种思路,下面会描述。path[i][j] = path[k][j] 达到 j 节点 的前驱节点修改为经过k到j的路径上去。
完整代码:
测试数据:
-
1. 基础版本
//Folyd
#include <iostream>
#include <vector>
#include <algorithm> using namespace std; const int INF = 0x3f3f3f3f;
const int MAX_POINT = ; //邻接矩阵保存点信息
int mapp[MAX_POINT][MAX_POINT];
//保存任意两点之间的最短路径上的节点
vector<int> trace_path[MAX_POINT][MAX_POINT]; void Folyd(int n) {
for (int k = ; k < n; k++)
for (int i = ; i < n; i++)
for (int j = ; j < n; j++)
if (mapp[i][j] > mapp[i][k] + mapp[k][j]) {
mapp[i][j] = mapp[i][k] + mapp[k][j];
trace_path[i][j].clear();
//放入 i---k 路径节点
for (int z = ; z < trace_path[i][k].size(); z++)
trace_path[i][j].push_back(trace_path[i][k][z]);
//放入 k---j 路径节点
for (int z = ; z < trace_path[k][j].size(); z++)
trace_path[i][j].push_back(trace_path[k][j][z]);
}
} void query(int from, int to) {
cout << "from " << from << " to " << to << " should cost " << mapp[from][to] <<"."<< endl;
cout << "trace_path: " ;
for (int i = ; i < trace_path[from][to].size(); i++)
cout<< trace_path[from][to][i] << " -> ";
cout << to << endl;
} int main(int argc, char const *argv[])
{
int n;
cout << "Please input gragh points:";
cin >> n;
//init container, 自己到自己默认 0,其他为 INF
for (int i = ; i < n; i++) {
mapp[i][i] = ;
for (int j = ; j < n; j++)
if (i != j)
mapp[i][j] = INF;
} int t = (n*(n - )) >> ;
// 最多输入 n(n -1)>>1 条边
cout << "Please input edges format a tuple (f, t , v), to end input via (-1, 0, 0)" << endl;
while (--t > ) {
int from, to, value;
cin >> from >> to >> value;
if (~from) {
//无向图
mapp[from][to] = value;
mapp[to][from] = value;
//每条路的前驱放入路径中
trace_path[from][to].push_back(from);
trace_path[to][from].push_back(to);
}
else
break;
} Folyd(n); //结果打表
cout << "====================" << endl;
for (int i = ; i < n; i++) { for (int j = ; j < n; j++)
cout << mapp[i][j] << "\t";
cout << endl;
}
cout << "====================" << endl;
while(){
int beginP, endP;
cout << "Please input begin point and end point:";
cin >> beginP >> endP;
query(beginP, endP);
}
return ;
}
2. 改进版本
//Folyd
//输入图,可以不连通
#include <iostream>
using namespace std; const int INF = 0x3f3f3f3f;
const int MAX_POINT = ;
const int NOTEXISTS = ~(0U); //邻接矩阵保存点信息
int mapp[MAX_POINT][MAX_POINT];
//path[i][j] = k ,表示从 i 到 j 最短路, k 邻接到j。
int path[MAX_POINT][MAX_POINT];
void Folyd(int n) {
//初始化路径数组
for (int i = ; i < n; i++)
for (int j = ; j < n; j++) {
if (mapp[i][j] - INF)
path[i][j] = i;
else
path[i][j] = NOTEXISTS;
} for (int k = ; k < n; k++)
for (int i = ; i < n; i++)
for (int j = ; j < n; j++)
if (mapp[i][j] > mapp[i][k] + mapp[k][j]) {
mapp[i][j] = mapp[i][k] + mapp[k][j];
path[i][j] = path[k][j];
}
} void print_path(int from, int to) {
if (path[from][to] != from)
print_path(from, path[from][to]);
cout << " -> " << to;
} int main(int argc, char const *argv[])
{
int n;
cout << "Please input gragh points:";
cin >> n; //init container
for (int i = ; i < n; i++) {
mapp[i][i] = ; //自己到自己默认 0
for (int j = ; j < n; j++)
if (i != j)
mapp[i][j] = INF;
} int t = (n*(n - )) >> ;
// 最多输入 n(n -1)>>1 条边
cout << "Please input edges format a tuple (f, t , v), to end input via (-1, 0, 0)" << endl;
while (--t > ) {
int from, to, value;
cin >> from >> to >> value;
if (~from) {
mapp[from][to] = value;
mapp[to][from] = value;
}
else
break;
}
Folyd(n); cout << "====================" << endl;
for (int i = ; i < n; i++) { for (int j = ; j < n; j++)
cout << mapp[i][j] << "\t";
cout << endl;
}
cout << "====================" << endl;
while () {
int beginP, endP;
cout << "Please input begin point and end point:";
cin >> beginP >> endP;
//print path
cout << "from " << beginP << " to " << endP << " should cost " << mapp[beginP][endP] << "." << endl;
if (path[beginP][endP] == NOTEXISTS)
cout << "No path!" << endl;
else {
cout << "trace_path: ";
cout << beginP;
print_path(beginP, endP);
cout << endl;
}
}
return ;
}
参考资料:
https://blog.csdn.net/start0609/article/details/7779042
https://blog.csdn.net/immiao/article/details/22199939
Folyd + 路径存储的更多相关文章
- DM 多路径存储
DM多路径存储 系统环境:RHEL5.4 small install selinux and iptables disabled主机规划:主机网卡软件station133eth0: 192.168. ...
- photoshop:把路径存储为形状
这个其实跟定义画笔步骤是一样的 路径存储为自定义形状 1.用路径选择工具(快捷键A),选中路径 2.菜单:编辑->定义自定形状 3.选择自定义形状工具(快捷键U),可以看到刚定义的形状 把当前形 ...
- RHEL 6.5----iscsi多路径存储
主机名 IP master eth0: 192.168.30.130(NAT) eth1: 192.168.17.130(VMNet4) node-1 eth0: 192.168.30.131(NAT ...
- ASP.Net 5 上传文件通过虚拟路径存储
先贴上代码 [HttpPost] public IActionResult ImportTeaching(IFormFile file) { string root = @"Temp/tea ...
- express实现前后端通信上传图片,存储数据库(mysql)傻瓜教程(三)完结篇
终于完成了所有自己想要的功能(鼓励下自己),虽然还是很简陋,但是还是挺有满足感的,哈哈. 附上前两篇的链接: 第一篇 第二篇 进入正题,在第二篇里面已经完成了连接数据库,并且实现了对数据库的增删改查, ...
- HTML5 LocalStorage 本地存储的用法
本地存储变量b的值: localStorage.setItem("b","isaac"); 本地获取变量b的值: localStorage.getItem(&q ...
- 【转】mysql保存图片技术决定:保存二进制文件还是只保存图片相对路径,图片放在硬盘上面?
最近遇到上面这个问题,一开始我就果断否决了数据库保存图片的策略,主要是太蠢!事实上我的决定是正确的,我仅仅理解为mysql读写性能提高的境界,具体为什么可以提高?很模糊,知道我看到了这里: 大佬做的实 ...
- Windows system 在python文件操作时的路径表示方法
file_path =(r'i:\vacpy\ch10\pi_digits.txt') #将文件路径存储在变量file_path中with open (file_path) as file_objec ...
- 多路径multipath配置,udev绑定
多路径multipath配置 以root用户登录 1.查看共享磁盘是否挂载成功 #fdisk -l 2.生成配置文件 #mpathconf --enable 修改配置文件权限 #chmod 644 / ...
随机推荐
- MSSQLServer——全国省份城市SQL语句
use hr create table dbo.province ( proID int primary key, proName ), keys ) ) ,'北京市','B'); ,'天津市','T ...
- WinAPI: GetModuleFileName、GetModuleHandle
原文:http://www.cnblogs.com/del/archive/2008/06/17/1223681.html unit Unit1; interface uses Windows, ...
- springboot 使用webflux响应式开发教程(二)
本篇是对springboot 使用webflux响应式开发教程(一)的进一步学习. 分三个部分: 数据库操作webservicewebsocket 创建项目,artifactId = trading- ...
- C++中long是什么类型
long long本质上还是整型,只不过是一种超长的整型. int型:32位整型,取值范围为-2^31 ~ (2^31 - 1) .long:在32位系统是32位整型,取值范围为-2^31 ~ (2^ ...
- angular 动态组件类型
出处:https://github.com/Penggggg/angular-component-practices 组件类型1:纯函数功能,而没有视图部分,即Factory(类似于$http) pr ...
- C# mvc读取模板并修改上传到web
C# mvc读取模板并修改上传到web 后台: public FileResult GetXls() { FileStream fs = new FileStream(System.Web.HttpC ...
- Detecting Client Connection in WCF Long Running Service (Heartbeat Implementation) z
Download source - 45.3 KB Introduction Hello everyone! This is my first blog on WCF and I hope that ...
- 二叉树的二叉链表存储结构及C++实现
前言:存储二叉树的关键是如何表示结点之间的逻辑关系,也就是双亲和孩子之间的关系.在具体应用中,可能要求从任一结点能直接访问到它的孩子. 一.二叉链表 二叉树一般多采用二叉链表(binary linke ...
- Nginx能干啥?
Nginx能干的事很多,很强大.官方文档详见点我. Nginx的命令行参数 -? | -h 打印帮助信息 -c file 读取指定配置文件,而不是默认的nginx.conf -g directives ...
- 正则表达式 (python)
正则表达式 在正则表达式中,如果直接给出字符,就是精确匹配. 用\d可以匹配一个数字,\w可以匹配一个字母或数字,所以: '00\d'可以匹配'007',但无法匹配'00A': '\d\d\d'可以匹 ...