单源最短路径 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 年 ...
随机推荐
- WPF学习12:基于MVVM Light 制作图形编辑工具(3)
本文是WPF学习11:基于MVVM Light 制作图形编辑工具(2)的后续 这一次的目标是完成 两个任务. 本节完成后的效果: 本文分为三个部分: 1.对之前代码不合理的地方重新设计. 2.图形可选 ...
- [转]合理使用ArrayMap代替HashMap
合理使用ArrayMap代替HashMap 2016年07月08日 15:34:44 阅读数:5938 转载请标注: 披萨大叔的博客 http://blog.csdn.net/qq_27258799/ ...
- sql server 2012 从删库到跑路
问题: 向sql server 2012单个数据库中导入1500万+条数据的时候,报错: 错误 0xc0202009: 数据流任务 1: SSIS 错误代码 DTS_E_OLEDBERROR.出现 O ...
- php 生成饼状图,折线图,条形图 通用类
生成饼状图,折线图,条形图通用的php类,这里使用的是百度 Echart. Echart 官方网站 http://echarts.baidu.com/ <?php class Echarts ...
- ASP.NET Web API FilterAttribute假想
偶然的测试发现API FilterAttribute没用引用只会初始化一次 比如: 如果是 Global Action Filter, 则全局只会初始化一次 针对于不同的Controller级别的Ac ...
- Perl语言入门: 斜线不是元字符,所以在不作为分隔符时不需要加上反斜线。
Perl语言入门: 斜线不是元字符,所以在不作为分隔符时不需要加上反斜线.
- xshell全局设置配色方案
新建XTerm1.xcs文件,将以下内容黏贴进去,保存退出 [XTerm] text=839496 cyan(bold)=93a1a1 text(bold)=408080 magenta=dd3682 ...
- RTP/RTCP协议详解
1.简介 目前,在IP网络中实现实时语音.视频通信和应用已经成为网络应用的一个主流技术和发展方向,本文详细介绍IP协议族中用于实时语音.视频数据传输的标准协议RTP( Real-time Transp ...
- 读懂CommonJS的模块加载
叨叨一会CommonJS Common这个英文单词的意思,相信大家都认识,我记得有一个词组common knowledge是常识的意思,那么CommonJS是不是也是类似于常识性的,大家都理解的意思呢 ...
- 万能的搜索--之DFS(二)
(一)深度优先搜索(DFS) 我们先给出深度优先的解决办法,所谓深度优先搜索,在迷宫问题里就是不撞南墙不回头,能走得深一点就尽量深一点.如果碰到了墙壁就返回前一个位置尝试其他的方向.在<啊哈!算 ...