首先两个算法都是常用于 求单源最短路径

关键部分就在于松弛操作 实际上就是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的更多相关文章

  1. 单源最短路径问题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 ...

  2. 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法

    Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...

  3. 单源最短路径问题之dijkstra算法

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 算法的原理 以源点开始,以源点相连的顶点作为向外延伸的顶点,在所有这些向外延伸的顶 ...

  4. 非负权值有向图上的单源最短路径算法之Dijkstra算法

    问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度.求解该问题的算法一般为Dijkstra算法. 假设图顶点个数为n,则针对 ...

  5. 单源最短路径—Bellman-Ford和Dijkstra算法

    Bellman-Ford算法:通过对边进行松弛操作来渐近地降低从源结点s到每个结点v的最短路径的估计值v.d,直到该估计值与实际的最短路径权重相同时为止.该算法主要是基于下面的定理: 设G=(V,E) ...

  6. 洛谷 P3371 【模板】单源最短路径(堆优化dijkstra)

    题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三 ...

  7. 【算法】Dijkstra算法(单源最短路径问题)(路径还原) 邻接矩阵和邻接表实现

    Dijkstra算法可使用的前提:不存在负圈. 负圈:负圈又称负环,就是说一个全部由负权的边组成的环,这样的话不存在最短路,因为每在环中转一圈路径总长就会边小. 算法描述: 1.找到最短距离已确定的顶 ...

  8. Bellman-Ford算法 - 有向图单源最短路径

    2017-07-27  08:58:08 writer:pprp 参考书目:张新华的<算法竞赛宝典> Bellman-Ford算法是求有向图单源最短路径的,dijkstra算法的条件是图中 ...

  9. Dijkstra 单源最短路径算法

    Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...

随机推荐

  1. 通俗易懂的Nhibernate教程(1) ----- 基本操作,映射,CURD

    网站架构: 1.图片 2.说明 Data  -----------------------   类库项目,数据访问层,由Nhibernate提供数据相关操作 Mapping ------------- ...

  2. 【学习笔记】后端中的MVC和前端MVVM的关系

  3. Git-往返github和本地

    将GitHub仓库Test弄到本地 本地新建文件夹Test 右击运行gitbash 在gitbash中输入git init 在github 仓库选择clone or download 复制链接http ...

  4. TabLayout.Tab(自定义)点击事件

    TabLayout是官方design包中的一个布局控件,这里不介绍它的基本使用,只是解决Tab(自定义)点击事件. //获取Tab的数量 Int tabCount = tabLayout.getTab ...

  5. Java Web开发之Spring | SpringMvc | Mybatis | Hibernate整合、配置、使用

    1.Spring与Mybatis整合 web.xml: <?xml version="1.0" encoding="UTF-8"?> <web ...

  6. Javaweb之xml

        1 XML概述     1.1 XML是什么? eXtensible Markup Language可扩展标记语言          1.2 XML作用         主要是用于描述数据,而 ...

  7. 聊聊JavaScript和Scala的表达式 Expression

    我们先看下面这段简单的JavaScript代码. 我在第10行调用了函数f,其中传入的第二个和第三个参数都是一个逗号表达式. 函数f的实现,会检查这两个参数的类型,如果是函数,则执行函数调用,再打印其 ...

  8. 设计模式、SOLID原则:组件与联系

    组件原则 - SRP The Single Responsibility Principle 单一责任原则 当需要修改某个类的时候原因有且只有一个.换句话说就是让一个类只做一种类型的责任,当这个类需要 ...

  9. HashMap Hashtable TreeMap LinkedHashMap 分析

    首先对hash的了解:就是关键字,和数据建立关系的映射. hash常用算法:假设我们中的字符有相应的内部编码,当然在实际过程中,我们不可能将所有的编码当做hash值. 平方取中法,将所得的内部编码平方 ...

  10. DROP DOMAIN - 删除一个用户定义的域

    SYNOPSIS DROP DOMAIN name [, ...] [ CASCADE | RESTRICT ] DESCRIPTION 描述 DROP DOMAIN 将从系统表中删除一个用户域. 只 ...