Graph theory problem (1): Shortest

Copyright: Code original, For reprint, please send an email to [email protected] or [email protected], or qq3145743347 https://blog.csdn.net/ebirth/article/details/91351892.

Overview summary graph theory problem (1)

For graph theory , we respect the algorithm is more familiar with, this time, I found a common focus algorithm.

  1. The shortest path algorithm (Dijkstra, SPFE, FLOYD)
  • Single Source Shortest algorithm Dijkstra

First, this algorithm is suitable for calculating the shortest path one point to another point, and the algorithm must not be negative ring. The slow speed of the algorithm, then sleep for only a small problem, as shown:
Here Insert Picture Description
this figure is the basic idea of seeking algorithm.
Algorithmic process:

  • Find the nearest point of the node from the node, it will mark him, to the collection U.
  • The point U is connected phthalic point edge is connected, U find not in the set.
  • Repeat the previous operation, to guide V = U, the search ends, the process finally ended.

Flowchart of an algorithm of this algorithm:
https://wenku.baidu.com/view/8a5c11303968011ca300916a.html
reference code:

#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e3 + 9;
const int M = 1e4 + 9;
const int inf = 0x3f3f3f3f;
struct edge {
int v, w, next;
edge() {}
edge(int _v, int _w, int _next) {
	v = _v;
	w = _w;
	next = _next;
}
} e[M << 1];
int head[N], len;
void init() {
	memset(head, -1, sizeof head);
	len = 0;
}
void add(int u, int v, int w) {
	e[len] = edge(v, w, head[u]);
	head[u] = len++;
}
void add2(int u, int v, int w) {
	add(u, v, w);
	add(v, u, w);
}
int n, m;
int dis[N];
bool vis[N];
void dijkstra(int u) {
memset(vis, false, sizeof vis);
memset(dis, inf, sizeof dis);
dis[u] = 0;
for (int i = 0; i < n; ++i) {
	int mi = inf;
	for (int j = 1; j <= n; ++j) {
		if (!vis[j] && dis[j] < mi) {
			mi = dis[u = j];
		}
	}	
if (mi == inf) {
	return;
}
vis[u] = true;
			for (int j = head[u]; ~j; j = e[j].next) {
	int v = e[j].v;
	int w = e[j].w;
				if (!vis[v] && dis[v] > dis[u] + w) {
	dis[v] = dis[u] + w;
				}
			}
		}
	}
int main() {
init();
int u, v, w;
cin >> n >> m;
while (m--) {
	cin >> u >> v >> w;
	add2(u, v, w);
}
dijkstra(1);
cout << dis[n] << endl;
return 0;
}

This is just a basic flow of the code, you can brush on the basis of the template, making modifications.
The basic idea is the starting point for the expansion of the center out layer (BFS + greedy), extended until to the end point.

This is our algorithms, therefore, can solve many problems.

3 3
1 2 5
2 3 5
3 1 2

Enter the data and see what happens!

  • Heap optimization Dijkstra

Positive algorithm for sparse graphs, we use and optimization.

#include <iostream>
#include <cstring>
#include <set>
using namespace std;
const int N = 1e3 + 9;
const int M = 1e4 + 9;
const int inf = 0x3f3f3f3f;
typedef pair<int, int> pall;
#define X first
#define Y second
struct edge {
int v, w, next;
edge() {}
edge(int _v, int _w, int _next) {
v = _v;
w = _w;
next = _next;
}
} e[M << 1];
int head[N], len;
void init() {
memset(head, -1, sizeof head);
len = 0;
}
void add(int u, int v, int w) {
e[len] = edge(v, w, head[u]);
head[u] = len++;
}
void add2(int u, int v, int w) {
add(u, v, w);
add(v, u, w);
}
int n, m;
int dis[N];
bool vis[N];
void dijkstra(int u) {
memset(vis, false, sizeof vis);
memset(dis, inf, sizeof dis);
dis[u] = 0;
}
int main() {
init();
int u, v, w;
cin >> n >> m;
while (m--) {
cin >> u >> v >> w;
add2(u, v, w);
}
dijkstra(1);
cout << dis[n] << endl;
return 0;
}

Find the minimum, and here is the core of ordinary Dijkstra differences, we just need to get the top of the heap element can be (automatically sort heap,
stack top element is the minimum we need). Then we put this element to the collection (mark is added to the meaning of the collection).

  • SPFA single-source shortest path algorithm
    in SPFA algorithm, using di representation from the source to the shortest vertex i, the additional use a queue to hold the apex upcoming expansion of
    the list, and use ingi to identify the vertex i is not in the queue.
    FIG:

    Space SPFA complexity is O (V), like the bit beat step sparse FIG. He used to run the queue, therefore, SPEA is just to upgrade the following column, not the kind of very much. To a certain extent, it can be considered by the BFS SPFA be transformed from ideas. Excluding from the right side to the right side or on a BFS FIG unit length, extended to the weighted graph, it was SPFA.

    Beat step algorithm:

  • Using a queue to hold a plurality of extension queues.

  • A queue with one element taken, relaxation and other points.

  • When all the points are not in the queue into the queue, then the program ends, the algorithm is completed.

bool inq[MAX_N];
int d[MAX_N]; // 如果到顶点 i 的距离是 0x3f3f3f3f,则说明不存在源点到 i 的最短路
void spfa(int s) {
	memset(inq, 0, sizeof(inq));
	memset(d, 0x3f, sizeof(d));
d[s] = 0;
inq[s] = true;
queue<int> q;
q.push(s);
while (!q.empty()) {
	int u = q.front();
	q.pop();
	inq[u] = false;
	for (int i = p[u]; i != -1; i = e[i].next) {
		int v = e[i].v;
		if (d[u] + e[i].w < d[v]) {
			d[v] = d[u] + e[i].w;
			if (!inq[v]) {
				q.push(v);
				inq[v] = true;
				}
			}
		}
	}
}

FIG algorithm: https://i.loli.net/2019/06/09/5cfcb3db1267062487.jpg
above code is the same in all structures, initializing with the same structure as the first algorithm of SPEA.
Analyzing negative ring SPEA algorithm:

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e3 + 9;
const int M = 1e4 + 9;
const int inf = 0x3f3f3f3f;
struct edge {
	int v, w, next;
	edge() {}
	edge(int _v, int _w, int _next) {
		v = _v;
		w = _w;
		next = _next;
}
} e[M << 1];
int head[N], len;
void init() {
	memset(head, -1, sizeof head);
	len = 0;
}
void add(int u, int v, int w) {
	e[len] = edge(v, w, head[u]);
	head[u] = len++;
}
void add2(int u, int v, int w) {
	add(u, v, w);
	add(v, u, w);
}
int n, m;
int main() {
init();
int u, v, w;
cin >> n >> m;
while (m--) {
	cin >> u >> v >> w;
	add2(u, v, w);
}
return 0;
}

Then you can run the program:

3 3
1 2 5
2 3 5
3 1 2
  • Floyd multi-source shortest path algorithm

Floyd algorithm for calculating a weighted graph is given the shortest path between any two vertices algorithm. Repeat several times compared to the single - source
shortest path algorithm, Floyd has a high efficiency, the advantages of short codes, in solving the shortest path graph theory topics more commonly used.
floyd algorithm to solve the negative ring (can be calculated shortest path between any two points) to the shortest path problem with multi-source to FIG FIG or absent. Often
adjacency matrix storage, time complexity of O (N2), the spatial complexity of O (N2).

Algorithms way:

  • If not through the first point, it is dp [k-1] [i] [j].
  • If after the first point, it is dp [k-1] [i] [j] + dp [k-1] [i] [j].

So it becomes:

dp[k][i][j] = min(dp[k − 1][i][j], dp[k − 1][i][k] + dp[k − 1][k][j])

So it becomes the following code:

int g[N][N]; // 邻接矩阵存图
int dp[N][N][N];
void floyd(int n) {
	for (int k = 0; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				if (k == 0) {
					dp[k][i][j] = g[i][j];
				} else {
					dp[k][i][j] = min(dp[k - 1][i][j], dp[k - 1][i][k] + dp[k - 1][k][j]);
				}
			}
		}
	}
}

We write the final form of Floyd, which is commonly used in writing, to optimize the space one-dimensional. And writing easier. Here we must note
is intended, it must be written to enumerate the intermediate point out the most. No attention to this, it is easy to order three cycles mistake, then bear
fruit that is wrong.
Just analytical results:

int g[N][N];
void floyd(int n) {
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
}

Algorithm here is complete, the next to introduce differential restraint system .

  • Differential restraint system

When we solve the differential restraint system, it can be converted to single-source shortest (or longest road) problem in graph theory.
Here Insert Picture Description
It will have a negative ring that can be so.

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e3 + 9;
const int M = 1e4 + 9;
const int inf = 0x3f3f3f3f;
struct edge {
	int v, w, next;
	edge() {}
	edge(int _v, int _w, int _next) {
		v = _v;
		w = _w;
		next = _next;
	}
} e[M << 1];
int head[N], len;
void init() {
	memset(head, -1, sizeof head);
	len = 0;
}
void add(int u, int v, int w) {
	e[len] = edge(v, w, head[u]);
	head[u] = len++;
}
void add2(int u, int v, int w) {
	add(u, v, w);
	add(v, u, w);
}
int n, m;
int dis[N], in[N];
bool vis[N];
bool spfa(int u) {
	memset(vis, false, sizeof vis);
	vis[u] = true;
	memset(dis, -1, sizeof dis);
	dis[u] = 0;
	memset(in, 0, sizeof in);
	in[u] = 1;
	queue<int> q;
	q.push(u);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		for (int j = head[u]; ~j; j = e[j].next) {
			int v = e[j].v;
			int w = e[j].w;
			if (dis[v] < dis[u] + w) { // 求最长路,和求最短路相反
				dis[v] = dis[u] + w;
				if (!vis[v]) {
					q.push(v);
					vis[v] = true;
					++in[v];
					if (in[v] > n + 1) {
						return true;
				}
			}
		}
	}
}
return false;
}
int main() {
init();
int u, v, w, op;
cin >> n >> m;
while (m--) {
	cin >> op;
	cin >> u >> v >> w;
}
if (op == 1) {
	add(u, v, -w);
}else if (op == 2) {
	add(v, u, w);
}else {
	add(u, v, -w);
	add(v, u, w);
}
for (int i = 1; i <= n; ++i) {
	add(0, i, 0);
}
if (spfa(0)) {
	cout << "no" << endl;
}else {
	for (int i = 1; i <= n; ++i) {
		cout << "x" << i << " = " << dis[i] << endl;
	}
}
return 0;
}

This is the difference constraint, now run your program:

4 3
1 1 2 3
2 3 2 2
3 3 4 1

This is the shortest period finished, the next phase (Euler).
The end of the current graph theory, next goodbye!

Guess you like

Origin blog.csdn.net/ebirth/article/details/91351892