1) Dijkstra

基本思路:更新每个点到原点的最短路径;寻找最短路径点进行下一次循环;循环次数达到 n - 1 次说明每个点到原点的最短路已成,停止程序。

 1  function Dijkstra(Graph, source):
2
3 create vertex set Q
4
5 for each vertex v in Graph: // Initialization
6 dist[v] ← INFINITY // Unknown distance from source to v
7 prev[v] ← UNDEFINED // Previous node in optimal path from source
8 add v to Q // All nodes initially in Q (unvisited nodes)
9
10 dist[source] ← 0 // Distance from source to source
11
12 while Q is not empty:
13 u ← vertex in Q with min dist[u] // Source node will be selected first
14 remove u from Q
15
16 for each neighbor v of u: // where v is still in Q.
17 alt ← dist[u] + length(u, v)
18 if alt < dist[v]: // A shorter path to v has been found
19 dist[v] ← alt
20 prev[v] ← u
21
22 return dist[], prev[]
// Dijkstra
#include <bits/stdc++.h>
using namespace std;
const int N = 25000 + 5, M = 62000 + 5;
const int inf = 2147483647;
int n, m, s, e, dis[N];
int first[N], nex[M], to[M], w[M], en;
bool v[N]; void add(int x, int y, int z) {
nex[++en] = first[x]; first[x] = en; to[en] = y; w[en] = z;
nex[++en] = first[y]; first[y] = en; to[en] = x; w[en] = z;
} int main() {
int x, y, z;
scanf("%d%d%d%d", &n, &m, &s, &e);
for (int i = 1; i <= n; i++)
dis[i] = inf;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
} dis[s] = 0; v[s] = true;
int k = s;
for (int i = 1; i <= n - 1; i++) {
int minlen = inf;
for (int j = first[k]; j; j = nex[j])
if (dis[k] + w[j] < dis[to[j]])
dis[to[j]] = dis[k] + w[j];
for (int j = 1; j <= n; j++) {
if ((!v[j]) && (dis[j] < minlen)) {
k = j;
minlen = dis[j];
}
}
v[k] = true;
} printf("%d\n", dis[e]);
return 0;
}
/* Dijkstra Optimized
* Au: H15teve
*/
#include <bits/stdc++.h>
// header <queue> included.
using namespace std; const int N = 200003, M = 1000003, inf = 2147483647; struct node {
int u, dis;
bool operator < (const node &n) const {
return dis > n.dis;
}
} temp; priority_queue<node> q; int d[N], n, m, s, head[N], nex[M], to[M], w[M], en;
bool v[N]; inline void add(int x, int y, int z) {
nex[++en] = head[x], head[x] = en,
to[en] = y, w[en] = z;
} int main() {
scanf("%d%d%d", &n, &m, &s);
for (int i = 1; i <= n; i++) d[i] = inf;
for (int i = 1, x, y, z; i <= m; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
} d[s] = 0, temp.u = s; q.push(temp); while (!q.empty()) {
temp = q.top(), q.pop();
if (v[temp.u]) continue;
v[temp.u] = true; for (int i = head[temp.u]; i; i = nex[i])
if (temp.dis + w[i] < d[to[i]])
d[to[i]] = temp.dis + w[i],
q.push((node) {to[i], d[to[i]]});
} for (int i = 1; i <= n; i++)
printf("%d ", d[i]);
return 0;
}

2) Kruskal

基本思路:按边长度从小到大排序,循环添加「不成环」的边;边数达到 n - 1 说明最小生成树已成,停止程序。

/* Kruskal
* Au: GG
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1000 + 3, M = 20000 + 3;
int dset[N], n, m; struct edge {
int x, y, w;
bool operator < (const edge &a) const { return w < a.w; }
} edges[M]; int find(int x) { return (dset[x] == -1) ? x : dset[x] = find(dset[x]); }
void join(int x, int y) { if (find(x) != find(y)) dset[find(x)] == find(y); } int Kruskal() {
memset(dset, -1, sizeof(dset));
sort(edges + 1, edges + m + 1);
int cnt = 0, tot = 0;
for (int i = 1; i <= m; i++) //循环所有已从小到大排序的边
if (find(edges[i].x) != find(edges[i].y)) { // (因为已经排序,所以必为最小)
join(edges[i].x, edges[i].y); // 相当于把边(u,v)加入最小生成树。
tot += edges[i].w;
cnt++;
if (cnt == n - 1) // 说明最小生成树已经生成
break;
}
return tot;
} int main() {
printf("Enter vertex number & edge number:\n");
scanf("%d%d", &n, &m);
printf("Enter information of %d edge(s):\n", m);
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &edges[i].x, &edges[i].y, &edges[i].w);
} printf("The weight of minimum spanning tree is %d.\n", Kruskal()); return 0;
}

3) Bellman-Ford

基本思路:更新每个点到原点的最短路径;循环次数达到 n - 1 次说明每个点到原点的最短路已成,停止程序。

// Bellman-Ford
// Au: GG
#include <bits/stdc++.h>
using namespace std;
const int maxn = 25000 + 5, maxm = 62000 + 5;
const int inf = 1000000001;
int n, m, s, e, en;
int from[maxm], to[maxm], w[maxm];
int dis[maxn], pre[maxm];
void add(int x, int y, int z) {
from[++en] = x; to[en] = y; w[en] = z;
}
int main() {
int x, y, z;
scanf("%d%d%d%d", &n, &m, &s, &e);
for (int i = 1; i <= n; i++)
dis[i] = inf;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
}
dis[s] = 0; pre[s] = 0;
for (int i = 1; i <= n - 1; i++)
for (int j = 1; j <= m; j++)
if (dis[from[j]] + w[j] < dis[to[j]]) {
dis[to[j]] = dis[from[j]] + w[j];
pre[to[j]] = from[j];
}
printf("%d\n", dis[e]);
return 0;
}

4) Floyd

基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间距离值。

procedure Floyd–Warshall(G)
1 let dist be a |V| × |V| array of minimum distances initialized to ∞ (infinity)
2 for each vertex v
3 dist[v][v] ← 0
4 for each edge (u,v)
5 dist[u][v] ← w(u,v) // the weight of the edge (u,v)
6 for k from 1 to |V|
7 for i from 1 to |V|
8 for j from 1 to |V|
9 if dist[i][j] > dist[i][k] + dist[k][j]
10 dist[i][j] ← dist[i][k] + dist[k][j]
11 end if
// Floyd
// Au: GG
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000 + 3;
const int inf = 1000000001;
int n, m;
int f[maxn][maxn];
int main() {
scanf("%d%d", &n, &m);
int i, j, k, a, b, w;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
f[i][j] = inf;
for (i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &w);
if (f[a][b] > w) f[a][b] = w, f[b][a] = w;
}
for (k = 1; k <= n; k++)
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
if (f[i][j] > f[i][k] + f[k][j])
f[i][j] = f[i][k] + f[k][j];
scanf("%d%d", &a, &b);
printf("%d", f[a][b]);
return 0;
}

5) SPFA

基本思路:更新每个点到原点的最短路径,保证「路径可变得更小的点」在队列中;队列空说明每个点到原点的最短路已成,停止程序。

procedure Shortest-Path-Faster-Algorithm(G, s)
1 for each vertex v ≠ s in V(G)
2 d(v) := ∞
3 d(s) := 0
4 offer s into Q
5 while Q is not empty
6 u := poll Q
7 for each edge (u, v) in E(G)
8 if d(u) + w(u, v) < d(v) then
9 d(v) := d(u) + w(u, v)
10 if v is not in Q then
11 offer v into Q
/* Shortest Path Faster Algorithm
* Au: GG
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1000 + 3, M = 10000 + 3;
int n, m, s, d[N], pre[N], enq[N];
bool inq[N];
int head[N], nex[M], to[M], w[N], en;
queue<int> q; void add(int x, int y, int z) {
nex[++en] = head[x]; head[x] = en; to[en] = y; w[en] = z;
nex[++en] = head[y]; head[y] = en; to[en] = x; w[en] = z;
} bool SPFA() {
memset(d, 0x7f, sizeof(d));
q.push(s); d[s] = 0; inq[s] = true; enq[s]++; while (!q.empty()) {
int a = q.front(); q.pop();
inq[a] = false;
for (int b = head[a]; b; b = nex[b])
if (d[a] + w[b] < d[to[b]]) {
d[to[b]] = d[a] + w[b];
pre[to[b]] = a;
if (!inq[to[b]]) {
q.push(to[b]);
enq[to[b]]++; if (enq[to[b]] >= n) return false;
inq[to[b]] = true;
}
}
}
return true;
} int main() {
int a, b, c;
printf("Enter vertex number, edge number & source point index:\n");
scanf("%d%d%d", &n, &m, &s);
printf("Enter information of %d edge(s):\n", m);
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
} if (SPFA()) {
for (int i = 1; i <= n; i++)
if (i != s) {
printf("Distance between source point to point %d is %d.\n", i, d[i]);
int p = i;
stack<int> ans;
printf(" Path: %d", s);
while (s != p) ans.push(p), p = pre[p];
while (!ans.empty()) printf(" -> %d", ans.top()), ans.pop();
printf("\n");
}
} else printf("The graph has negative circle!\n"); return 0;
}

「重拾最短路」可参考 61mon.com 的博客:

  1. Dijkstra (Link )
  2. Bellman-Ford (Link )
  3. SPFA (Link )
  4. 总结 (Link )

Reference

  1. internal (blog/83) by SJoshua
  2. Stack Overflow. Trying to understand Dijkstra's Algorithm[DB/OL]. Link , 2017-08-04

图论 Algorithms的更多相关文章

  1. HDU 5489 Difference of Clustering 图论

    Difference of Clustering Problem Description Given two clustering algorithms, the old and the new, y ...

  2. QBXT Day 5图论相关

    图论是NOIP的一个非常重要的考点,换句话说,没有图论,NOIP的考纲就得少一大半(虽然很NOIP没有考纲) 图论这玩意吧,和数论一样是非常变态的东西,知识点又多又杂,但是好在一个事,他比较直观比较好 ...

  3. 【五一qbxt】day5 图论

    图论 学好图论的基础: 必须意识到图论hendanteng xuehuifangqi(雾 图 G = (V,E) 一般来说,图的存储难度主要在记录边的信息 无向图的存储中,只需要将一条无向边拆成两条即 ...

  4. [leetcode] 题型整理之图论

    图论的常见题目有两类,一类是求两点间最短距离,另一类是拓扑排序,两种写起来都很烦. 求最短路径: 127. Word Ladder Given two words (beginWord and end ...

  5. 剪短的python数据结构和算法的书《Data Structures and Algorithms Using Python》

    按书上练习完,就可以知道日常的用处啦 #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving wit ...

  6. OpenCascade Modeling Algorithms Fillets and Chamfers

    Modeling Algorithms Fillets and Chamfers 造型算法——倒圆与倒角 eryar@163.com 一.倒圆Fillet Constructor 1. BRepFil ...

  7. OpenCascade Modeling Algorithms Boolean Operations

    Modeling Algorithms Boolean Operations of Opencascade eryar@163.com 布尔操作(Boolean Operations)是通过两个形状( ...

  8. 【图论】深入理解Dijsktra算法

    1. Dijsktra算法介绍 Dijsktra算法是大牛Dijsktra于1956年提出,用来解决有向图单源最短路径问题.但不能解决负权的有向图,若要解决负权图则需要用到Bellman-Ford算法 ...

  9. Machine Learning Algorithms Study Notes(3)--Learning Theory

    Machine Learning Algorithms Study Notes 高雪松 @雪松Cedro Microsoft MVP 本系列文章是Andrew Ng 在斯坦福的机器学习课程 CS 22 ...

随机推荐

  1. 类File

    * File类常用的构造方法: * (1)File(String s);//由s确定File对象的文件名 * (2)File(String directory,String s);//由directo ...

  2. 编译的时候出现"/usr/bin/ld: cannot find -lz

    编译的时候出现"/usr/bin/ld: cannot find -lz"错误,需要安装zlib-dev这个包,在线安装命令为:apt-get install zlib1g-dev ...

  3. 个人对BFC的见解

    BFC:块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level BOX参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关. BFC的生成 既然上文提到BFC是一块渲 ...

  4. 20190905 Lombok常用注解

    Lombok常用注解 val 用于声明类型,将从初始化表达式推断出类型,仅适用于局部变量和foreach循环,而不适用于字段.声明的局部变量为final变量. Java自带类型推断随着JDK版本提升越 ...

  5. [19/05/15-星期三] HTML_body标签(超链接标签和锚点)

    一.超链接标签 <html> <head> <meta charset="UTF-8"> <title>04 body超链接标签学习 ...

  6. Mybatis-学习笔记(2)Mybatis配置文件

      3>typeAliases:类型别名.2种指定方式. 1>给某个类起个别名 <typeAliases> <typeAlias type="com.lfy.b ...

  7. poj-2516.minimum cost(k次费用流)

    Minimum Cost Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 19883   Accepted: 7055 Des ...

  8. SCUT - 365 - 鹏哥的数字集合 - wqs二分 - 斜率优化dp

    https://scut.online/p/365 https://www.luogu.org/problemnew/solution/P2365 写这篇的时候还不是很明白,看一下这个东西. http ...

  9. 攻防世界--simple-check-100

    测试文件:https://adworld.xctf.org.cn/media/task/attachments/2543a3658d254c30a89e4ea7b8950c27.zip 这道题很坑了, ...

  10. 行人重识别(ReID) ——数据集描述 CUHK03

    数据集简介 CUHK03是第一个足以进行深度学习的大规模行人重识别数据集,该数据集的图像采集于香港中文大学(CUHK)校园.数据以"cuhk-03.mat"的 MAT 文件格式存储 ...