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 / ...
随机推荐
- css3 animation运用
animation:mymove 5s infinite; @keyframes mymove { from {left:0px;} to {left:200px;} } @-webkit-keyfr ...
- roadflow asp.net core版工作流引擎更新发布
ROADFLOW CORE (.NET CORE工作流引擎)更新说明 1.RoadFlow全新工作流平台采用.NET CORE 2.1重构,结构更简单,逻辑梳理更清析,性能有了很大的提升. 2.表单设 ...
- mysqlcppconn之ConnectOptionsMap的使用
由来 继上一篇文章, 发现之前写的一篇文章中断线重连部分是错误的, 也是现在翻阅了源码才知道 想要自动重连, 必须使用ConnectOptionsMap才可以 但由于官方代码没有做好导出部分的处理, ...
- idea 出现 java.lang.OutOfMemoryError: PermGen space
今天在项目启动时候,刚刚启动 就 报了 Exception in thread "http-bio-8080-exec-1" 之后 出现了 java.lang.OutOfMemor ...
- CSS中DIV只出现竖向滚动条且内容自动换行
只需要设置如下的样式即可: <div id="testDiv" style="overflow-x: hidden; word-break:break-all;bo ...
- SQL Server ->> 自动创建表并从文件加载数据
这个存储过程自动创建表并从文件加载数据. 有一点需要说明的是Excel 12.0驱动是兼容了Excel 97-2003和Excel 2007两者格式的Excel文件. CREATE PROCEDURE ...
- zt 设计模式六大原则(3):依赖倒置原则
下面说法对不对? 父类将算法(逻辑)封装起来,子类实现细节:这个就叫DIP(依赖倒置:Dependency Inversion Principles),模板模式就是这个原则的实现.如果在父类中加一个t ...
- python数据结构(整理)
http://www.cnblogs.com/yupeng/p/3413763.html 1. 单链表 链表的定义: 链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点 ...
- luogu P1642 规划
嘟嘟嘟 看到最后让求一个比值,应该得往01规划上去想.令x = ∑v[i] / ∑c[i],则x * ∑c[i] = ∑v[i], ∑(v[i] - x * c[i]) = 0. 于是可以二分x(注意 ...
- 练习:HPH 数据
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...