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 / ...
随机推荐
- CentOS 7 禁用IPV6以提高网速
方法 1 编辑文件/etc/sysctl.conf,$vi /etc/sysctl.conf添加下面的行: net.ipv6.conf.all.disable_ipv6 = net.ipv6.conf ...
- [PE格式分析] 4.IMAGE_FILE_HEADER
源代码如下: typedef struct _IMAGE_FILE_HEADER { +04h WORD Machine; // 运行平台 +06h WORD NumberOfSections; // ...
- ArrayList 与 List 关系与代码示例 - Java
关系 List 是 Java Interface, ArrayList 是 Java Class,它们都属于 java.util 包. Java List 是有序的集合(ordered collect ...
- 论组织资源 #F315
论组织资源 #F315 2016-02-29 yevon_ou 水库论坛 论组织资源 #F315 首先,让我们看一段长微博. 转:五毛大战美分,基层民猪那破事... 就是小区业委会的事,根据业委会相 ...
- div浮层,滚动条移动,保持位置不变的4种方法
div浮层,滚动条移动,保持位置不变的4种方法 div在顶部不变.滚动条滚动,div还是在顶部! 直接上传源码 了: 方法一: <!DOCTYPE html PUBLIC "-//W3 ...
- JAVA中的那些名词解释!
1.JDO: (Java Data Object )是Java对象持久化的新的规范,也是一个用于存取某种数据仓库中的对象的标准化API.作用:用于存取某种数据仓库中的对象 2.JPA: JPA是Jav ...
- P vs NP
Complexity Class Computational problem Decision Problems Model of computation Time-complexity classe ...
- win10系统 WMI Provider Host cpu 占用过高
今天上班,发现系统有点卡,QQ总是没响应. 打开任务管理器,发现有一个程序- WMI Provider Host 占用cpu竟然高达80% 然后通过事件查看器发现是一个pid为9832的程序造成的 然 ...
- Mysql学习---全国省市区以及邮编数据库
更多下载
- 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.5.调优实战
高性能硬件上的程序部署策略 在高性能硬件上部署程序,目前主要有两种方式: 通过64位JDK来使用大内存. -- 缺点:GC停顿时间长 使用若干个32位虚拟机建立逻辑集群来利用硬件资源. -- 思 ...