最短路算法Floyed, Dijkstra, Bellman-Ford, SPFA

Floyed算法,复杂度o(n^3);

更新i->j的距离,通过中介点k,如果能够通过k使得i->j的距离更短,那么更新。

代码

void Folyed() {
    for (int k = 0; k < n; k++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i != j && i != k && j != k && d[i][j] > d[i][k] + d[k][j]) {
					d[i][j] = d[i][k] + d[k][j];
				}
			}
		}
	}
}

Dijkstra算法,普通复杂度O(n^2),堆优化O(nlgn)

有个集合s,和原始图G,一个最短距离数组d。从起点开始,每次添加一个u,如果能够从中介点u更新到u所有的邻接点v的最短距离,那么当前可以更新的是起点到v的最短距离d[v]。直到s中包括所有点,算法结束,最后d数组就是起点到其他所有点的最短距离。

堆优化的话,就避免很多重复边的判断。

void Dijkstra(int st, int ed) {
	memset(d, INF, sizeof(d));
	memset(vis, false, sizeof(vis));
	d[st] = 0;
	for (int i = 0; i < n; i++) {
		int u = -1, MIN = INF;
		for (int j = 0; j < n; j++) {
			if (vis[j] == false && d[j] < MIN) {
				MIN = d[j];
				u = j;
			}
		}
		if (u == -1) return;
		vis[u] = true;
		for (int v = 0; v < n; v++) {
			if (vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]) {
				d[v] = d[u] + G[u][v];
			}
		}
	}
}

堆优化。 

struct edge {
	int v;
	int d;//距离
	edge(){}
	edge(int _v, int _d) {
		v = _v;
		d = _d;
	}
};
vector<edge> E[maxn];
void Clear() {
	for (int i = 0; i < maxn; i++) {
		E[i].clear();
	}
	memset(pre, 0, sizeof(pre));
}
struct node {
	int v;
	int d;
	bool operator<(const node &a)const{
		return d > a.d;
	}
};
void Dijkstra(int st, int ed) {
	memset(d, INF, sizeof(d));
	memset(minCost, INF, sizeof(minCost));
	memset(vis, false, sizeof(vis));
	d[st] = 0;
	minCost[st] = 0;
	priority_queue<node> q;
	q.push(node{st, 0});
	while (!q.empty()) {
		node f = q.top(); q.pop();
		int u = f.v;
		if (vis[u] == true) continue;
		vis[u] = true;
		for (int i = 0; i < E[u].size(); i++) {
			int v = E[u][i].v;
			if (vis[v] == true) continue;
			if (d[v] > d[u] + E[u][i].d) {
				d[v] = d[u] + E[u][i].d;
				pre[v] = u;
				q.push(node{v, d[v]});
			}
		}
	}
}

Bellman-Ford,复杂度O(n*E),顶点数n,边数E

void bellman-ford() {
	for (int i = 0; i < n - 1; i++) {//最多n-1次
		for (int u = 0; u < n; u++) {
			for (int j = 0; j < Adj[u].size(); j++) {
				int v = Adj[u][j].v;
				int dis = Adj[u][j].dis;
				if (d[u] + dis < d[v]) {
					d[v] = d[u] + dis;
				}
			}
		}
	}
}

SPFA,复杂度O(k*E),k平均值一般等于2

spfa算法就是对bellman-ford的一种队列优化,避免了很多无意义的判断和操作。

bool SPFA(int s) {
	memset(inq, false, sizeof(inq));
	memset(num, 0, sizeof(num));
	memset(d, INF, sizeof(d));
	prority_queue<int> q;
	q.push(s);
	inq[s] = true;
	num[s]++;
	d[s] = 0;
	while (!q.empty()) {
		int u = q.top(); q.pop();
		inq[u] = false;
		//
		for (int j = 0; j < Adj[u].size(); j++) {
			int v = Adj[u][j].v;
			int dis = Adj[u][j].dis;
			if (d[u] + dis < d[v]) {
				d[v] = d[u] + dis;
				if (!inq[v]) {
					inq[v] = true;
					q.push(v);
					num[v]++;
					if (num[v] > n-1) return false;
				}
			}
		}
	}
	return true;
}

 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/qq_34649947/article/details/82940784
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞