Dijkstra算法修改 + dfs算法的总结
Dijkstra + dfs
参考Dijkstra算法的改进
前提:Dijkstra算法的思路和实现请看最短路径算法之二:Dijkstra总结
介绍
Dijkstra算法和dfs算法的结合主要解决最短路径的边权之和、点权之和以及打印最短路径结点等问题。
通过Dijkstra算法找出单源点最短路径,在通过dfs 算法遍历最短路径中的结点。主要实现的方法是在Dijkstra算法每次更新dis数组的时候对可变大小的数组(vector)进行插入清除等操作,将每次更新的最短路径结点的前驱结点加入到 vector 中。最后在 dfs 算法中通过不断的递归获取前驱结点并加到另一个最短路径数组中(vector path)。最后打印path 就可以得到最短路径经过的结点(具体实现方法请看下文问题实例)。
我之前遇到的问题
我原来的思路是在Dijkstra算法中先初始化 dis 数组(存放开始结点到各结点的最短距离)。然后在通过遍历查找dis中最小的点并标记更新dis数组和pre(存放各结点的前驱结点),最后导致在dfs算法中出现问题(dfs不会有到边界的情况)。原因是我在Dijkstra算法中优先对dis数组进行了初始化,然后在遍历。这相当于我跳过了第一次从开始结点到目标结点时没有将开始结点当做前驱结点加入到 pre 中,所以dfs 不会有 (end == begin)。
修改(已对上篇博客进行修改)
将原来对dis初始化删除,只需要对 dis [ begin ] = 0。
Dijkstra算法的变化
dfs算法核心代码
//将当前结点的加入到临时路径中temppath.push_back(D); //遍历结点 D 的前驱结点 for(int i = 0; i < pre[D].size(); i++){dfs(pre[D][i]); } //能执行到这说明这条最短路径已经遍历结束//回溯 temppath.pop_back();
具体案例
旅行者地图给出了高速公路沿线城市之间的距离,以及每条高速公路的成本。
现在你应该编写一个程序来帮助旅行者决定从他/她出发的城市到目的地的最短路径。
如果这样的最短路径不是唯一的,你应该输出最小代价的路径,它保证是唯一的。
输入规格:
每个输入文件包含一个测试用例。
每一种情况都以一行包含4个正整数N、M、S和D开始,
其中N(≤500)是城市的数量(因此城市编号从0到N-1);
M是高速公路的数量;S和D分别是出发城市和目的地城市。
然后是M行,每一行提供一条公路的信息,格式如下:
城市,城市,距离,花费
输出规范:
对于每个测试用例,在一行中打印从起点到目的地的最短路径上的城市,
然后是路径的总距离和总成本。数字之间必须用空格隔开,并且在输出结束时必须没有多余的空格。
Sample Input:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Sample Output:
0 2 3 3 40
代码
//最短距离是指 从开始城市到目标城市的最短距离
//最短路径是指 最短距离一样的不同路径
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int inf = 888888;
int N,M,S,D; //城市,关系,开始,结束
int ans1 = inf; //花费之和
int map[100][100]; //图
int sum[100][100]; //花费
int dis[100]; //每次城市间的最短距离
int vis[100]; //已经确认的城市间最短距离
vector<int> pre[100]; //每个城市最短路径的前驱结点
vector<int> path; //最短路径
vector<int> temppath; //临时最短路径
//ps: pre[100] 可看作一个二维数组
// path、temppath 可看作一个一维数组 //误区:原来思路:dijkstra算法首先初始化 dis从开始结点到各结点的距离,
//从而导致在遍历更新 dis 时没有将开始结点加入到前驱 pre 中(因为将前驱结点是从第二趟开始的,第一次被跳过了),
//最终导致在调用dfs时出问题(dfs不会有边界的情况)
//更改:不用初始化最开始dis到各点的距离, 只需要初始化 开始结点到开始结点为 dis[S] = 0;
//
//Dijkstra算法
void dijkstra(int S)
{dis[S] = 0; //关键 //循环遍历 for(int i = 0; i < N; i++){int temp = -1; //标记找到的最小值 int aaa = inf; //进行迭代松弛 for(int j = 0; j < N; j++){if( !vis[j] && dis[j]< aaa){aaa = dis[j];temp = j;}} if(temp == -1) return;vis[temp] = 1;//根据找到的最短路径更新 disfor(int j = 0; j < N; j++){if(!vis[j])//找到没有确定最短路径的结点 {//判断是否是最短路径 if(dis[j] > dis[temp] + map[temp][j]){//更新dis dis[j] = dis[temp] + map[temp][j];//清空 pre 之前存的数据 ,重新将最短路径的前驱结点加入 pre[j].clear();pre[j].push_back(temp);//如果经过 temp 前驱结点后的最短距离一样 }else if(dis[j] == (dis[temp] + map[temp][j])){//存在多条最短距离一样,但最短路径不一样,将其加入 pre pre[j].push_back(temp);}}} } } //dfs算法
/*
关键问题:如果存在多条最短距离相同但最短路径不同的路线对其进行判断哪条路径花费最少(点权之和)
核心:将各结点的前驱结点加入临时路径中,实现获得一条完整最短距离的最短路径的各结点
*/
void dfs(int D)
{//出口边界 if(D == S)//如果 开始城市等于结束城市 退出 {//主要内容,对已经获得的最短路径 temppath进行判断是否是花费最少的 //将最后一个城市加入 temppathtemppath.push_back(D); int num = 0,id1,id2; //num 为 这条最短路径的花费之和 //i 从 开始城市开始遍历。i 不能等于 1 是因为会造成越界 for(int i = temppath.size()-1; i > 0 ; i--){id1 = temppath[i]; //前面城市 id2 = temppath[i-1]; //后面城市 num += sum[id1][id2]; //对经过的城市花费进行累加 }//如果这条边比之前的最短路径花费还少 if(num < ans1){//更新最终的最短路径 ans1 = num; path = temppath;}//回溯temppath.pop_back();return; } //将当前结点的加入到临时路径中temppath.push_back(D); //遍历结点 D 的前驱结点 for(int i = 0; i < pre[D].size(); i++){dfs(pre[D][i]); } //能执行到这说明这条最短路径已经遍历结束//回溯 temppath.pop_back();
}int main(int argc, char** argv)
{while(cin >> N >> M >> S >> D){//初始化for(int i = 0; i < N; i++){for(int j = 0; j < N; j++){if(i==j){map[j][i] = 0;} else {map[i][j] = map [j][i] = inf;sum[i][j] = sum[j][i] = inf;} }}fill(dis,dis+N,inf);fill(vis,vis+N,0);//输入 for(int i = 0; i < M; i++){int a,b,c,d; cin >> a >> b >> c >> d;map[a][b] = map[b][a] = c; //各边关系 sum[a][b] = sum[b][a] = d; //各边花费 }dijkstra(S);dfs(D);//经过Dijkstra 和 dfs 之后获得花费最少的最短路径 path //输出结果 :经过的城市,总距离(开始城市到目标城市的距离),花费之和(dfs求出) for(int i = path.size()-1; i >= 0; i--){cout << path[i] << " ";} cout << dis[D] << " " << ans1 << endl;}return 0;
}
Dijkstra算法修改 + dfs算法的总结相关推荐
- 八皇后BFS算法、DFS算法、A*算法代码理解
代码参考了Python:DFS/BFS/UCS解决八皇后问题_流动的风与雪的博客-CSDN博客 和Python:GBF/A*算法解决八皇后问题_流动的风与雪的博客-CSDN博客 但是我花了两天时间才看 ...
- 算法之DFS算法框架
DFS算法框架 前言 前面说到了BFS,就少不了DFS了~ 算法分析 DFS全称是深度优先搜索,听这个名字就知道,这个算法就是一直不断往下的"深度"搜索,思想就是:一直往深处走,直 ...
- 图论:BFS算法与DFS算法的C++实现
关于算法的准确性,本人只测试了比较简单的情况,两个算法是否存在未发现的漏洞,本人不做任何担保 BFS算法: 类似于树的层序遍历,需要借助队列实现` 算法的基本流程:起始点--探索未遍历的邻接点--未遍 ...
- 【算法笔记】二分图最大权匹配 - KM算法(dfs版O(n4) + bfs版O(n3))
整理的算法模板合集: ACM模板 匈牙利算法又称为 KM 算法,可以在 O(n3)O(n^3)O(n3) 时间内求出二分图的 最大权完美匹配 . 考虑到二分图中两个集合中的点并不总是相同,为了能应用 ...
- 最短路径—Dijkstra算法和Floyd算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Di ...
- 最短路径-Dijkstra算法与Floyd算法
最短路径-Dijkstra算法与Floyd算法 原文:https://www.cnblogs.com/smile233/p/8303673.html 一.最短路径 ①在非网图中,最短路径是指两顶点之间 ...
- 最短路径:Dijkstra算法和Floyd算法
一.Dijkstra算法(单个顶点到其他顶点的最短距离) 定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层 ...
- 最短路径Dijkstra算法和Floyd算法整理、
转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径-Dijkstra算法和Floyd算法 Dijks ...
- 【最短路径】:Dijkstra算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法
求最短路径最常用的算法有: Dijkstra算法.SPFA算法.Bellman-Ford算法和Floyd-Warshall算法. Dijkstra算法.SPFA算法.Bellman-Ford算法这三个 ...
最新文章
- MySQl数据库必会sql语句(提升版)
- Android 有些机型hint不显示
- css3 卡片亮光_利用css3实现文字亮光特效的代码
- Christmas Present
- java 单字节_java文件读取。(单字节读取和按行读取读取)
- Python中的魔法属性
- SIFT算法总结:用于图像搜索
- appium 环境搭建 java
- 基于JAVA+SpringMVC+Mybatis+MYSQL的学生社团管理系统
- 指针07:指针和函数
- 笔记本--摄像头驱动--找不到相机--浏览器打开相机失败--未检测到摄像头--剩下的标题我就不想了--太长了
- Windows 10 RTM 官方正式版
- 【图像融合】基于matlab小波变换图像融合【含Matlab源码 392期】
- SAP查询销售订单库存
- elementUI的tree组件搜索过滤,可识别拼音,且不区分大小写
- Win10无法开机修复方法
- 拼多多免费版 自动回复 关键词回复 提高3分钟回复率
- 交易心得(简要总结)
- 使用计算机视觉和深度学习创建现代 OCR 管道
- 2021年危险化学品经营单位安全管理人员考试内容及危险化学品经营单位安全管理人员考试资料