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. Python写一个自动点餐程序

    Python写一个自动点餐程序 为什么要写这个 公司现在用meican作为点餐渠道,每天规定的时间是早7:00-9:40点餐,有时候我经常容易忘记,或者是在地铁/公交上没办法点餐,所以总是没饭吃,只有 ...

  2. Java JDK安装教程以及JDK多版本间快速切换配置

    原本想自己写一篇,结果在网上发现一篇写的特别好的博文,大家可以去原网址围观浏览加点赞, 只是搬运工+迷弟. 原文地址:https://blog.csdn.net/qq_38916130/article ...

  3. 简历内容-resume

    1.TCP.UDP通信  服务器客户端  网络层 2.http协议 通信  网络编程  应用层  根据公司给出的应用层协议开发指定程序: 3.json  cjson Cjson解析器 4.freeRT ...

  4. Java多态性应用——多态数组、多态参数

    多态数组: Person[] person = {new Person("张三", 32), new Student("李四", 21, 120, 90.0), ...

  5. Java学习day9面向对象编程2-方法的可变个数的参数和方法的参数传递

    一.方法的可变个数的参数. 问题:我们能够打印的信息都是来源于方法的参数,也就是形参的传递.那如何要给方法传递不同的参数? .1.采用数组形参来定义方法 public static void test ...

  6. P2731 骑马修栅栏 (欧拉路径)

    [题目描述] John是一个与其他农民一样懒的人.他讨厌骑马,因此从来不两次经过一个栅栏.你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次.John能从任何一 ...

  7. 使用OFBIZ的理由和不使用OFBIZ的理由

    1 使用OFBIZ的理由 1.1 什么是OFBIZ OFBIZ是由Sourceforge维护的一个最著名的开源项目之一,提供创建基于最新J2EE/XML规范和技术标准,构建大型企业级.跨平台.跨数据库 ...

  8. Angular.js 使用获取验证码按钮实现-倒计时

    获取验证码界面效果如图: 需要实现以下逻辑 按钮不可选 --输入电话号码,按钮可选 --点击获取,进入倒计时,按钮不可选 --倒计时结束,回到初识状态 核心代码: var cd = 60; var t ...

  9. FFmpeg从入门到出家(HEVC在RTMP中的扩展)

    由金山云视频云技术团队提供:FFmpeg从入门到出家第三季: 为推进HEVC视频编码格式在直播方案中的落地,经过CDN联盟讨论,并和主流云服务厂商达成一致,规范了HEVC在RTMP/FLV中的扩展,具 ...

  10. java 中的引用类型

    GC基本原理 GC (Garbage Collection)的基本原理:将内存中不再被使用的对象进行回收,GC中用于回收的方法称为收集器,由于GC需要消耗一些资源和时间,Java在对对象的生命周期特征 ...