图论 Algorithms
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 的博客:
Reference
- internal (blog/83) by SJoshua
- Stack Overflow. Trying to understand Dijkstra's Algorithm[DB/OL]. Link
, 2017-08-04
图论 Algorithms的更多相关文章
- HDU 5489 Difference of Clustering 图论
Difference of Clustering Problem Description Given two clustering algorithms, the old and the new, y ...
- QBXT Day 5图论相关
图论是NOIP的一个非常重要的考点,换句话说,没有图论,NOIP的考纲就得少一大半(虽然很NOIP没有考纲) 图论这玩意吧,和数论一样是非常变态的东西,知识点又多又杂,但是好在一个事,他比较直观比较好 ...
- 【五一qbxt】day5 图论
图论 学好图论的基础: 必须意识到图论hendanteng xuehuifangqi(雾 图 G = (V,E) 一般来说,图的存储难度主要在记录边的信息 无向图的存储中,只需要将一条无向边拆成两条即 ...
- [leetcode] 题型整理之图论
图论的常见题目有两类,一类是求两点间最短距离,另一类是拓扑排序,两种写起来都很烦. 求最短路径: 127. Word Ladder Given two words (beginWord and end ...
- 剪短的python数据结构和算法的书《Data Structures and Algorithms Using Python》
按书上练习完,就可以知道日常的用处啦 #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving wit ...
- OpenCascade Modeling Algorithms Fillets and Chamfers
Modeling Algorithms Fillets and Chamfers 造型算法——倒圆与倒角 eryar@163.com 一.倒圆Fillet Constructor 1. BRepFil ...
- OpenCascade Modeling Algorithms Boolean Operations
Modeling Algorithms Boolean Operations of Opencascade eryar@163.com 布尔操作(Boolean Operations)是通过两个形状( ...
- 【图论】深入理解Dijsktra算法
1. Dijsktra算法介绍 Dijsktra算法是大牛Dijsktra于1956年提出,用来解决有向图单源最短路径问题.但不能解决负权的有向图,若要解决负权图则需要用到Bellman-Ford算法 ...
- Machine Learning Algorithms Study Notes(3)--Learning Theory
Machine Learning Algorithms Study Notes 高雪松 @雪松Cedro Microsoft MVP 本系列文章是Andrew Ng 在斯坦福的机器学习课程 CS 22 ...
随机推荐
- 【EWM系列】SAP EWM创建warehouse task的函数
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP EWM创建warehouse ...
- Vue路由注意事项
一.vue中路由的使用 1.定义组件 <template> <div class="hello"> <h1 @click="info&quo ...
- [2019杭电多校第二场][hdu6602]Longest Subarray(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6602 题目大意为求最长的区间,满足C种数字在区间内要么不出现,要么出现的次数都不小于K. 大致的分析一 ...
- [2019杭电多校第二场][hdu6599]I Love Palindrome String(回文自动机&&hash)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6599 题目大意为求字符串S有多少个子串S[l,r]满足回文串的定义,并且S[l,(l+r)/2]也满足 ...
- 干货!小白入门Python数据科学全教程
前言 本文讲解了从零开始学习Python数据科学的全过程,涵盖各种工具和方法 你将会学习到如何使用python做基本的数据分析 你还可以了解机器学习算法的原理和使用 说明 先说一段题外话.我是一名数据 ...
- html表格单元格添加斜下框线的方法
一.分隔单元格的方法 1.用“transform: rotate(-55deg);”把一条水平线旋转一定角度就成斜线了 2.利用以下命令调整分割线位置等. :after :before transfo ...
- R语言常用数据管理
1.变量的重命名 (1)交互式编辑器修改变量名 若要修改数据集x中的变量名,键入fix(x)即可打开交互式编辑器的界面.若数据集为矩阵或数据框,单击交互式编辑器界面中对应要修改的变量名,可手动输入新的 ...
- canvas画随机的四位验证码
效果图如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- Flutter 实际开发常用工具类(全局提示,请求封装,token缓存,验证码倒计时、常用窗帘动画及布局)
介绍: 一星期从入门到实际开发经验分享及总结 代码传送门github Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面.未来App开发 ...
- iOS App中 使用 OpenSSL 库
转自:http://blog.csdn.net/kmyhy/article/details/6534067 在你的 iOS App中 使用 OpenSSL 库 ——译自x2on的“Tutorial: ...