单源最短路径 Bellman_ford 和 dijkstra
首先两个算法都是常用于 求单源最短路径
关键部分就在于松弛操作 实际上就是dp的感觉
if (dist[e.to] > dist[v] + e.cost)
{
dist[e.to] = dist[v] + e.cost;
...
}
bellman_ford O(E*V) 但是配合队列可以 有spfa 可以达到O(kE)
http://www.360doc.com/content/13/1208/22/14357424_335569176.shtml
并且bellman_ford还适用于负边 并且可以利用最多循环V-1次的性质 判断是否存在负圈(如果循环超过V-1次 说明有负圈 因为没重复走着负圈一次 都伴随着更新)
并且因为松弛操作是针对于每条边的遍历也可以用向前星存
#include <iostream>
#include <stdio.h>
#include <fstream>
#include <string.h>
#define MAXV 10007
#define MAXE 1007
#define INF 0x3f3f3f3f
using namespace std; int V, E; struct Edge
{
int from, to, cost;
}edge[MAXE]; int bellman_ford(int s, int d)//求单源最短路径
{
int dist[MAXV];
fill (dist, dist+V+, INF);
dist[s] = ;
while (true)//直至update不在更新
{
bool update = false;
for (int i = ; i < E; i++)
{
if (dist[edge[i].from] != INF && dist[edge[i].to] > dist[edge[i].from] + edge[i].cost)
{
dist[edge[i].to] = dist[edge[i].from] + edge[i].cost;
update = true;
}
}
if (!update) break;
}
return dist[d];
}
//while(true) 循环中最多循环V-1次 复杂度是O(V*E)
//如果存在 从s可达的负圈 那么在第V次循环时也会更新 可以用这个性质来检查负圈
//如果一开始把dist都初始化为0 那么可以检查出所有的负圈
//检查负边 是负边 返回true
//P.S 圈表示基本回路
bool isNegtive()
{
int dist[MAXV];
memset(dist, , sizeof(dist));//单纯查负圈
for (int i = ; i < V; i++)
{
for (int i = ; i < E; i++)
{
Edge e = edge[i];
if (dist[e.to] < dist[e.from] + e.cost )
{
dist[e.to] = dist[e.from] + e.cost;
if (i == V-)//如果第V次还更新 那么就有负圈
return true;
}
}
}
return false;
}
int main()
{
ifstream cin ("in.txt");
cin >> V >> E;
for (int i = ; i < E; i++)
{
cin >> edge[i].from >> edge[i].to >> edge[i].cost;
}
cout << bellman_ford(, ) << endl;
}
dijkstra 普通写法O(V^2)
但是 dijkstra的特点 --->>是针对每一个点 通过它所对应的边更新 e.to的节点
每次取出的是离原点sorce 最近的点 所以就可以使用优先队列 那么就变成O(V*logV)
并且因为“是针对每一个点 通过它所对应的边更新 e.to的节点 ” 那么也很好试用向前星
#include <iostream>
#include <string.h>
#include <fstream>
#include <stdio.h>
#include <queue>
#define MAXV 10007
#define MAXE 1007
#define INF 0x3f3f3f3f
using namespace std; int V, E;
//迪杰特斯拉好像不是很好用向前星
//这个算法是针对每一个点更新 而向前星存储的是边的信息 要查找点就比较复杂 //用邻接矩阵存储 O(V^2)的算法 int cost[MAXV][MAXV];
int dijkstra(int s, int d)
{
int dist[MAXV];
bool use[MAXV];
fill(dist, dist+MAXV, INF);
memset(use, false, sizeof(use));
dist[s] = ;
while (true)
{
int v = -;
for (int i = ; i <= V; i++)//找一个最近的 未使用过的点
{
if (!use[i] && (v == - || dist[i] < dist[v])) v = i;
}
if (v == -) break;
use[v] = true;
for (int i = ; i <= V; i++)
{
dist[i] = min(dist[i], dist[v] + cost[v][i]);
}
}
return dist[d];
} //使用优先队列(也就是heap优化)O(E*logV)
//针对边来dp 这里可以用向前星存储了
struct Edge
{
int to, n, next;
}edge[MAXE];
int num = ;
int head[MAXV];
void Add(int from, int to, int c)
{
edge[num].n = c;
edge[num].to = to;
edge[num].next = head[from];//从头插入
head[from] = num++;
}
void init()//初始化
{
ifstream cin("in.txt");
memset(edge, -, sizeof(edge));
memset(head, -, sizeof(head));
cin >> V >> E;
for (int j = ; j < E; j++)
{
int from , to , c;
cin >> from >> to >> c;
Add(from, to, c);
}
} typedef pair<int, int> P;//first 表示与s的距离, second表示点的编号
int pre[MAXV];//记录前驱节点 在每次dist[j] = dist[k] + cost[k][j]更新时记录在到j的最短路径上的前驱节点就是k
int fast_dijkstra(int s, int d)
{
int dist[MAXV];
priority_queue<P, vector<P>, greater<P> > que;//用优先队列存储点的信息 每次弹出距离最短的点O(logV)
fill(dist, dist+MAXV, INF);
dist[s] = ;
que.push(P(, s));
while (!que.empty())
{
P p = que.top();
que.pop();
if (dist[p.second] < p.first) continue;
int t = head[p.second];
while (t != -)
{
Edge e = edge[t];
if (dist[e.to] > dist[p.second] + e.n)
{
dist[e.to] = dist[p.second] + e.n;
pre[e.to] = p.second;
que.push( P(dist[e.to], e.to) );
}
t = e.next;
}
}
return dist[d];
} int main()
{
/*
ifstream cin("in.txt");
cin >> V >> E;
for (int i = 1; i <= V; i++)
for (int j = 1; j <= V; j++)
cost[i][j] = INF;//不存在时 cost为INF
for (int j = 0; j < E; j++)
{
int from , to , c;
cin >> from >> to >> c;
cost[from][to] = c;
}
int ans = dijkstra(1, 7);
*/
init();
int ans = fast_dijkstra(,);
cout << ans << endl;
//这样路径即还原了
int t = pre[];
cout << << " ";
while(t != )
{
cout << t << " ";
t = pre[t];
}
cout << <<endl;
}
单源最短路径 Bellman_ford 和 dijkstra的更多相关文章
- 单源最短路径问题2 (Dijkstra算法)
用邻接矩阵 /* 单源最短路径问题2 (Dijkstra算法) 样例: 5 7 0 1 3 0 3 7 1 2 4 1 3 2 2 3 5 2 4 6 3 4 4 输出: [0, 3, 7, 5, 9 ...
- 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法
Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...
- 单源最短路径问题之dijkstra算法
欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 算法的原理 以源点开始,以源点相连的顶点作为向外延伸的顶点,在所有这些向外延伸的顶 ...
- 非负权值有向图上的单源最短路径算法之Dijkstra算法
问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度.求解该问题的算法一般为Dijkstra算法. 假设图顶点个数为n,则针对 ...
- 单源最短路径—Bellman-Ford和Dijkstra算法
Bellman-Ford算法:通过对边进行松弛操作来渐近地降低从源结点s到每个结点v的最短路径的估计值v.d,直到该估计值与实际的最短路径权重相同时为止.该算法主要是基于下面的定理: 设G=(V,E) ...
- 洛谷 P3371 【模板】单源最短路径(堆优化dijkstra)
题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三 ...
- 【算法】Dijkstra算法(单源最短路径问题)(路径还原) 邻接矩阵和邻接表实现
Dijkstra算法可使用的前提:不存在负圈. 负圈:负圈又称负环,就是说一个全部由负权的边组成的环,这样的话不存在最短路,因为每在环中转一圈路径总长就会边小. 算法描述: 1.找到最短距离已确定的顶 ...
- Bellman-Ford算法 - 有向图单源最短路径
2017-07-27 08:58:08 writer:pprp 参考书目:张新华的<算法竞赛宝典> Bellman-Ford算法是求有向图单源最短路径的,dijkstra算法的条件是图中 ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
随机推荐
- AS 开发环境配置
安装时不用设置代理(proxy). 建议选择标准安装,自定义安装容易选掉一些功能.插件. SDK Tools里的(HAXM installer)有时会未安装,安装完需检查(HAXM installer ...
- Javascript中setTimeout()以及clearTimeout( )的使用
setTimeout setTimeout( ) 是属于 window 的 method, 这是用来设定一个时间,时间到了, 就会执行一个指定的 方法.练习一:等候三秒才执行的 alert( )set ...
- rmdir
rmdir——删除空目录 remove empty directories 命令所在路径:bin/rmdir 示例: # rmdir /tmp/japan/longze 删除/tmp/japan/目录 ...
- 一行命令杀掉defunct进程
一行命令杀掉defunct进程 今天在杀掉defunc过程中一直搞不完,索性写一行命令,注意先看懂谨慎使用 ps -ef|grep defunct|awk '{print " ps -ef| ...
- docker使用阿里云镜像加速器(属于自己的专属加速器)
https://cr.console.aliyun.com/cn-shanghai/mirrors
- Python3简明教程(六)—— 数据结构
简单的来说,数据结构(data structure)是计算机中存储.组织数据的方式.比如我们之前使用过的列表就是一种数据结构,在这里我们还会深入学习它.之前也有简单的介绍. 列表 >>&g ...
- Graveyard LA3708
白书第一章例题4 思维. 先固定一点不动,假设最后一共N个点,那么编号为0,1,...N-1, 0不动,原来的n个点分别占据i/n*N的位置(记为pos),移动到pos四舍五入的位置即可. 证明一:有 ...
- CAD交互绘制直线(网页版)
用户可以在CAD控件视区任意位置绘制直线. 主要用到函数说明: _DMxDrawX::DrawLine 绘制一个直线.详细说明如下: 参数 说明 DOUBLE dX1 直线的开始点x坐标 DOUBLE ...
- ubuntu命令行转换图片像素大小
convert -resize 512x256 00433.png 00001.png 1.512和256之间是x(就是字母那个x),用' * '反而会报错 2.这个命令会按照原图的比例进行转换 3. ...
- 任务备忘(已经完成):用python写一个格式化xml字符串的程序
功能: 1.将xml中多余的空格,换行符去掉,让xml字符串变成一行. 2.将xml中添加缩进,使用print能正确打印添加缩进后的字符串. 思路: 采用正则表达式来判断xml中字符串的类型: 1.文 ...