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 / ...
随机推荐
- 鼠标事件-拖拽(不能拖出窗口的div)
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- Ubuntu 下 /etc/resolv.conf文件总是自动清除问题的解决方案
最近学习Linux,在虚拟机中安装的是Ubuntu操作系统,用了几天发现Ubuntu无法上网,打开命令终端,输入命令: ping www.baidu.com -c2 结果显示名称无法识别,而直接与宿主 ...
- 申请单位iOS开发者账号
没有AppleID的需要先申请:此处略过: 1.登录苹果开发者官网(https://developer.apple.com),网速比较慢,多试几次 2. 点击 Enroll 切换到 简体中文 我以下述 ...
- WinAPI: OpenProcess、GetExitCodeProcess、TerminateProcess (测试强制关闭 OICQ)
原文:http://www.cnblogs.com/del/archive/2008/03/10/1098502.html //声明: {返回进程的句柄} OpenProcess( dwDesir ...
- 【Udacity】机器学习性能评估指标
评估指标 Evaluation metrics 机器学习性能评估指标 选择合适的指标 分类与回归的不同性能指标 分类的指标(准确率.精确率.召回率和 F 分数) 回归的指标(平均绝对误差和均方误差) ...
- KLEE错误汇报一:One phenomenon after the execution using klee
https://github.com/klee/klee/issues/649#issuecomment-300424204 Hi, all, If you write test.c wit ...
- GIT团队合作探讨之二--Pull Request
pull request是github/bitbucket给开发人员实现便利合作提供的一个feature.他们提供一个用户友好的web界面在进代码之前来讨论这些变更. 简单说,pull request ...
- February 17 2017 Week 7 Friday
The very essence of romance is uncertainty. 浪漫的精髓就在于它充满种种可能. If you want a happy life with enduring ...
- ArcSde服务启动后又停止
问题:突然发现ArcSde服务无法启动,“ArcSde服务启动后又停止,......” 环境:Win7+ArcSDE10 +Oracle11g 由于本人使用ArcSde时间不长,基本没有遇到过什么问题 ...
- GO语言(六)接口使用
<music> |------<src> |-------<library> |-------manager.go |-------manager_test.go ...