Ⅰ:Dijkstra单源点最短路

1.1Dijkstra

  1. const int MAX_N = 10000;
  2. const int MAX_M = 100000;
  3. const int inf = 0x3f3f3f3f;
  4. struct edge {
  5. int v, w, next;
  6. } e[MAX_M];
  7. int p[MAX_N], eid, n;
  8. void mapinit() {
  9. memset(p, -1, sizeof(p));
  10. eid = 0;
  11. }
  12. void insert(int u, int v, int w) { // 插入带权有向边
  13. e[eid].v = v;
  14. e[eid].w = w;
  15. e[eid].next = p[u];
  16. p[u] = eid++;
  17. }
  18. void insert2(int u, int v, int w) { // 插入带权双向边
  19. insert(u, v, w);
  20. insert(v, u, w);
  21. }
  22. int dist[MAX_N]; // 存储单源最短路的结果
  23. bool vst[MAX_N]; // 标记每个顶点是否在集合 U 中
  24. bool dijkstra(int s) {
  25. memset(vst, 0, sizeof(vst));
  26. memset(dist, 0x3f, sizeof(dist));
  27. dist[s] = 0;
  28. for (int i = 0; i < n; ++i) {
  29. int v, min_w = inf; // 记录 dist 最小的顶点编号和 dist 值
  30. for (int j = 0; j < n; ++j) {
  31. if (!vst[j] && dist[j] < min_w) {
  32. min_w = dist[j];
  33. v = j;
  34. }
  35. }
  36. if (min_w == inf) { // 没有可用的顶点,算法结束,说明有顶点无法从源点到达
  37. return false;
  38. }
  39. vst[v] = true; // 将顶点 v 加入集合 U 中
  40. for (int j = p[v]; j != -1; j = e[j].next) {
  41. // 如果和 v 相邻的顶点 x 满足 dist[v] + w(v, x) < dist[x] 则更新 dist[x],这一般被称作“松弛”操作
  42. int x = e[j].v;
  43. if (!vst[x] && dist[v] + e[j].w < dist[x]) {
  44. dist[x] = dist[v] + e[j].w;
  45. }
  46. }
  47. }
  48. return true; // 源点可以到达所有顶点,算法正常结束
  49. }

1.2Dijkstra堆优化

  1. const int MAX_N = 10000;
  2. const int MAX_M = 100000;
  3. const int inf = 0x3f3f3f3f;
  4. struct edge {
  5. int v, w, next;
  6. } e[MAX_M];
  7. int p[MAX_N], eid, n;
  8. void mapinit() {
  9. memset(p, -1, sizeof(p));
  10. eid = 0;
  11. }
  12. void insert(int u, int v, int w) { // 插入带权有向边
  13. e[eid].v = v;
  14. e[eid].w = w;
  15. e[eid].next = p[u];
  16. p[u] = eid++;
  17. }
  18. void insert2(int u, int v, int w) { // 插入带权双向边
  19. insert(u, v, w);
  20. insert(v, u, w);
  21. }
  22. typedef pair<int, int> PII;
  23. set<PII, less<PII> > min_heap; // 用 set 来伪实现一个小根堆,并具有映射二叉堆的功能。堆中 pair<int, int> 的 second 表示顶点下标,first 表示该顶点的 dist 值
  24. int dist[MAX_N]; // 存储单源最短路的结果
  25. bool vst[MAX_N]; // 标记每个顶点是否在集合 U 中
  26. bool dijkstra(int s) {
  27. // 初始化 dist、小根堆和集合 U
  28. memset(vst, 0, sizeof(vst));
  29. memset(dist, 0x3f, sizeof(dist));
  30. min_heap.insert(make_pair(0, s));
  31. dist[s] = 0;
  32. for (int i = 0; i < n; ++i) {
  33. if (min_heap.size() == 0) { // 如果小根堆中没有可用顶点,说明有顶点无法从源点到达,算法结束
  34. return false;
  35. }
  36. // 获取堆顶元素,并将堆顶元素从堆中删除
  37. auto iter = min_heap.begin();
  38. int v = iter->second;
  39. min_heap.erase(*iter);
  40. vst[v] = true;
  41. // 进行和普通 dijkstra 算法类似的松弛操作
  42. for (int j = p[v]; j != -1; j = e[j].next) {
  43. int x = e[j].v;
  44. if (!vst[x] && dist[v] + e[j].w < dist[x]) {
  45. // 先将对应的 pair 从堆中删除,再将更新后的 pair 插入堆
  46. min_heap.erase(make_pair(dist[x], x));
  47. dist[x] = dist[v] + e[j].w;
  48. min_heap.insert(make_pair(dist[x], x));
  49. }
  50. }
  51. }
  52. return true; // 存储单源最短路的结果
  53. }
  54. //输出数据 最短路长度存储在dst数组中
  55. int main(){
  56. init();
  57. scanf("%d%d",&n,&m);
  58. int u,v,w;
  59. for(int i=1;i<=m;i++){
  60. scanf("%d%d%d",&u,&v,&w);
  61. insert(u,v,w);
  62. insert(v,u,w);
  63. }
  64. dijkstra(1);
  65. cout<<dst[n]<<endl;
  66. return 0;
  67. }

1.3优先队列优化dij

  1. const int MAX_N = 10000;
  2. const int MAX_M = 100000;
  3. const int inf = 0x3f3f3f3f;
  4. struct edge {
  5. int v, w, next;
  6. } e[MAX_M];
  7. int p[MAX_N], eid, n;
  8. void mapinit() {
  9. memset(p, -1, sizeof(p));
  10. eid = 0;
  11. }
  12. void insert(int u, int v, int w) { // 插入带权有向边
  13. e[eid].v = v;
  14. e[eid].w = w;
  15. e[eid].next = p[u];
  16. p[u] = eid++;
  17. }
  18. void insert2(int u, int v, int w) { // 插入带权双向边
  19. insert(u, v, w);
  20. insert(v, u, w);
  21. }
  22. int dist[MAX_N]; // 存储单源最短路的结果
  23. bool vst[MAX_N]; // 标记每个顶点是否在集合 U 中
  24. struct node {
  25. int u;
  26. int dist;
  27. node(int _u, int _dist) : u(_u), dist(_dist) {}
  28. bool operator < (const node &x) const {
  29. return dist > x.dist;
  30. }
  31. }; // 记录点的结构体
  32. bool dijkstra(int s) {
  33. // 初始化 dist、小根堆和集合 U
  34. memset(vst, 0, sizeof(vst));
  35. memset(dist, 0x3f, sizeof(dist));
  36. priority_queue<node> min_heap;
  37. dist[s] = 0;
  38. min_heap.push(node(s, 0));
  39. while (!min_heap.empty())
  40. // 获取堆顶元素,并将堆顶元素从堆中删除
  41. int v = min_heap.top().u;
  42. min_heap.pop();
  43. if (vst[v]) {
  44. continue;
  45. }
  46. vst[v] = true;
  47. // 进行和普通 dijkstra 算法类似的松弛操作
  48. for (int j = p[v]; j != -1; j = e[j].next) {
  49. int x = e[j].v;
  50. if (!vst[x] && dist[v] + e[j].w < dist[x]) {
  51. dist[x] = dist[v] + e[j].w;
  52. min_heap.push(node(x, dist[x]));
  53. }
  54. }
  55. }
  56. return true;
  57. }

Ⅱ.SPFA求负权图最短路

2.1SPFA代码

  1. const int MAX_N = 10000;
  2. const int MAX_M = 100000;
  3. const int inf = 0x3f3f3f3f;
  4. struct edge {
  5. int v, w, next;
  6. } e[MAX_M];
  7. int p[MAX_N], eid, n;
  8. void mapinit() {
  9. memset(p, -1, sizeof(p));
  10. eid = 0;
  11. }
  12. void insert(int u, int v, int w) { // 插入带权有向边
  13. e[eid].v = v;
  14. e[eid].w = w;
  15. e[eid].next = p[u];
  16. p[u] = eid++;
  17. }
  18. void insert2(int u, int v, int w) { // 插入带权双向边
  19. insert(u, v, w);
  20. insert(v, u, w);
  21. }
  22. //开始SPFA
  23. bool inq[MAX_N];
  24. int d[MAX_N]; // 如果到顶点 i 的距离是 0x3f3f3f3f,则说明不存在源点到 i 的最短路
  25. void spfa(int s) {
  26. memset(inq, 0, sizeof(inq));
  27. memset(d, 0x3f, sizeof(d));
  28. d[s] = 0;
  29. inq[s] = true;
  30. queue<int> q;
  31. q.push(s);
  32. while (!q.empty()) {
  33. int u = q.front();
  34. q.pop();
  35. inq[u] = false;
  36. for (int i = p[u]; i != -1; i = e[i].next) {
  37. int v = e[i].v;
  38. if (d[u] + e[i].w < d[v]) {
  39. d[v] = d[u] + e[i].w;
  40. if (!inq[v]) {
  41. q.push(v);
  42. inq[v] = true;
  43. }
  44. }
  45. }
  46. }
  47. }

2.2SPFA判断负环

使用一个数组(in[max_n])统计每个点入队次数,当某个点入队次数>n就是存在负环


  1. int dis[N],in[N];
  2. bool vis[N];
  3. bool spfa(int u){
  4. memset(vis,false,sizeof(vis));
  5. vis[u] = true;
  6. memset(dis,0x3f,sizeof(dis));
  7. dis[u] = 0;
  8. memset(in,0,sizeof in);
  9. in[u] = 1;
  10. queue<int> q;
  11. q.push(u);
  12. while(!q.empty()){
  13. u = q.front();
  14. q.pop();
  15. vis[u] = false;
  16. for(int j=head[u];~j;j = e[j].fail){
  17. int v = e[j].v;
  18. int w = e[j].w;
  19. if(dis[v] > dis[u] + w){
  20. dis[v] = dis[u] + w;
  21. if(!vis[v]){
  22. q.push(v);
  23. vis[v] = true;
  24. ++in[v];
  25. if(in[v] > n){
  26. return true;
  27. }
  28. }
  29. }
  30. }
  31. }
  32. return false;
  33. }

Ⅲ:floyd多源点最短路

3.1floyd模板

  1. const int inf = 0x3f3f3f3f;
  2. int g[MAX_N][MAX_N]; // 算法中的 G 矩阵
  3. // 首先要初始化 g 矩阵
  4. void init() {
  5. for (int i = 0; i < n; ++i) {
  6. for (int j = 0; j < n; ++j) {
  7. if (i == j) {
  8. g[i][j] = 0;
  9. } else {
  10. g[i][j] = inf;
  11. }
  12. }
  13. }
  14. }
  15. // 插入一条带权有向边
  16. void insert(int u, int v, int w) {
  17. g[u][v] = w;
  18. }
  19. // 核心代码
  20. void floyd() {
  21. for (int k = 0; k < n; ++k) {
  22. for (int i = 0; i < n; ++i) {
  23. for (int j = 0; j < n; ++j) {
  24. if (g[i][k] + g[k][j] < g[i][j]) {
  25. g[i][j] = g[i][k] + g[k][j];
  26. }
  27. }
  28. }
  29. }
  30. }
  31. int main(){
  32. //输入顶点个数
  33. //初始化
  34. //输入邻接矩阵
  35. }

最短路模板|堆优化Dijkstra,SPFA,floyd的更多相关文章

  1. BZOJ 3040 最短路 (堆优化dijkstra)

    这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...

  2. 几个小模板:topology, dijkstra, spfa, floyd, kruskal, prim

    1.topology: #include <fstream> #include <iostream> #include <algorithm> #include & ...

  3. NEU 1664 传送(最短路基础 堆优化Dijkstra)

    题目描述 小A最近喜欢上一款游戏:游戏把地图分了一些区域,这些区域可能会重叠,也可能不会. 游戏中有一项传送技能,改传送技能只能将在同一区域的两个地方使用.小A可以利用区域中重叠部分来实现从某一区域到 ...

  4. 模板—堆优化dijkstra

    ];]; void dijkstra(int s) { memset(dis,0x7f,sizeof(dis));ma(v); priority_queue<pair<int,int> ...

  5. 堆优化Dijkstra计算最短路+路径计数

    今天考试的时候遇到了一道题需要路径计数,然而蒟蒻从来没有做过,所以在考场上真的一脸懵逼.然后出题人NaVi_Awson说明天考试还会卡SPFA,吓得我赶紧又来学一波堆优化的Dijkstra(之前只会S ...

  6. POJ 3635 - Full Tank? - [最短路变形][手写二叉堆优化Dijkstra][配对堆优化Dijkstra]

    题目链接:http://poj.org/problem?id=3635 题意题解等均参考:POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]. 一些口胡: ...

  7. 【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost

    [题目大意] 给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案. [思路] 在堆优化Dijkstra中,用pre记录前驱.如果新方案 ...

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

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

  9. PAT-1030 Travel Plan (30 分) 最短路最小边权 堆优化dijkstra+DFS

    PAT 1030 最短路最小边权 堆优化dijkstra+DFS 1030 Travel Plan (30 分) A traveler's map gives the distances betwee ...

随机推荐

  1. 写jquery插件(转载)

    如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论下jq ...

  2. upstream模块调度算法

    反向代理调度算法,轮询算法--——领导如何挑选小弟.迎宾小姐如何挑选服务员. 调度一般分为两类,第一类为静态调度算法,即负载均衡器根据自身设定的规划进行分配,不需要考虑节点的情况,例如,rr.wrr. ...

  3. mysql批量更新的两种方式效率试验<二>

    Mysql两种批量更新的对比 简介: mysql搭载mybits框架批量更新有两种方式,一种是在xml中循环整个update语句,中间以‘:’隔开,还有一种是使用case when 变相实现批量更新, ...

  4. 找不到main

    用eclipse写代码的时候,写了一个简单的程序,编译的时候突然出现“错误: 在类 com.test.demo 中找不到 main 方法, 请将 main 方法定义为: public static v ...

  5. .net 程序加密

    .net 程序加密,一般是对生成的exe文件或者dll直接进行加壳,配合加密锁或者许可进行授权控制,既能保证安全性,又控制软件的使用. 加壳工具的选择 一般要考虑几点,第一是加壳的安全性,不能被轻易脱 ...

  6. 小程序自定义tabBar,动态控制tabBar

    最近做项目的时候,突然来了个小特殊的需求,根据客户的类型来动态显示底部的tabBar菜单.当时我就有点小懵逼了,这个不是小程序自带的组件么?还要做成动态?这就有点尴尬了..... 不过也只是一时尴尬而 ...

  7. 2.1 Html

    一.Head中常用标签 <head>元素出现在文档的开头部分,会书写一些和浏览器中的配置信息. <head>与</head>之间的内容不会在浏览器的文档窗口显示,但 ...

  8. 关闭图形界面下普通用户关机重启命令- 7.x - CentOS

    vim /etc/polkit-/rules.d/-inhibit-shutdown.rules polkit.addRule(function(action, subject) { if (acti ...

  9. Android -- 从源码带你从EventBus2.0飚到EventBus3.0

    1,最近看了不少的面试题,不管是百度.网易.阿里的面试题,都会问到EventBus源码和RxJava源码,而自己只是在项目中使用过,却没有去用心的了解它底层是怎么实现的,所以今天就和大家一起来学习学习 ...

  10. CentOS 7 通过SQLmap进行SQL注入

    安装SQLmap: IP:192.168.94.11 渗透测试演练系统DVWA: IP:192.168.94.111 通过SQLmap检测SQL注入漏洞 : 1.安装SQLmap漏洞查看工具 2.安装 ...