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. Linux 下在后台运行进程:nohup,setsid,& 以及 tmux

    参考: Linux 技巧:让进程在后台可靠运行的几种方法 ssh 登录了远程服务器时,如果在前台运行耗时较长的任务, 当 ssh 掉线或关闭窗口时会导致命令停止运行. hup 与 nohup 当用户注 ...

  2. 应用安全 - 软件漏洞 - Jira漏洞汇总

    CVE-2019-8451 ssrf url = url + '/plugins/servlet/gadgets/makeRequest?url=' + host + '@www.baidu.com/ ...

  3. “希希敬敬对”队软件工程第九次作业-beta冲刺第一次随笔

    队名:  “希希敬敬对” 龙江腾(队长) 201810775001 杨希                   201810812008 何敬上 201810812004 今日讨论会议照片一张: 每个人 ...

  4. [Web 前端] 010 css 常用的边框设置

    css 常用边框属性 概览 参数 释义 border u设置边框属性(可以多个) border-color 边框颜色 border-style 边框样式solid 实线,dotted 点状线,dash ...

  5. (4.23)SQL Server中的加密

    转自:https://www.cnblogs.com/CareySon/archive/2012/04/01/SQL-SERVER-Encryption.html 简介 加密是指通过使用密钥或密码对数 ...

  6. Java-JavaMail邮件开发(1)Java Mail

    1.仅使用Java Mail 使用163邮箱作为代理服务器: 引入依赖: <dependency> <groupId>com.sun.mail</groupId> ...

  7. Python学习-第一天-函数和模块的使用

    目录 Python学习-第一天总结 print输出的一种简单格式 函数参数之可变参数 模块管理函数 if else语句的单行实现(简洁) 变量作用域 函数书写格式 Python学习-第一天总结 pri ...

  8. ofbiz idea 启动

    1.下载gradle并安装到本地 2.idea引入gradle 3.gradle右键选择refresh,项目会重新编译并加载gradle的task 4.可以再编译一下 5.没问题的话打开,jar ap ...

  9. 利用 Python 进行批量更改文件后缀

    利用 Python 进行批量更改文件后缀 代码 import os files = os.listdir('.') for file_name in files: portion = os.path. ...

  10. javascript(DOM)实例

    JavaScript学习笔记 JS补充笔记 实例之跑马灯,函数创建.通过ID获取标签及内部的值,字符串的获取与拼接.定时器的使用 使用定时器实现在console中打印内容 Dom选择器使用与调试记录 ...