最短路径问题的复习整理(2)

对最短路径问题(1)的补充

Bellman-Ford Algorithm(贝尔曼福德算法)

相对于迪杰斯特拉算法,它在没有负圈的情况最多更新V-1次,因此它适用于存在负边的情况,并且可以判断是否存在负圈(判断是否更新了V次以上)。

代码实现:

//贝尔曼福德算法 O(VE) 适用于负边 
//下面例子是对DAG进行操作 
#include<iostream>
#include<cstdio>
#include<vector>
#define MAX_V 100
#define MAX_E 100
#define INF 0x3f3f3f3f
using namespace std;
struct edge{
	int from, to, cost;
};
int d[MAX_V];
edge es[MAX_E];//DAG,无需构成邻接矩阵或邻接表,直接写入边即可 
int V, E;
void shortest_path(int s){//从顶点s出发 
	for(int i = 0; i < V; i++)	d[i] = INF;
	d[s] = 0;
	while(true){//最多执行V-1次 若进行了V次以上,则存在负圈 
		bool flag = false;
		for(int i = 0; i < E; i++){
			edge e = es[i];
			if(d[e.from] != INF && d[e.to] > d[e.from] + e.cost){
				d[e.to] = d[e.from] + e.cost;
				flag = true;
			}
		}
		if(!flag) break;
	}
}
int main(){
	cin >> V >> E;
	for(int i = 0; i < E; i++) cin >> es[i].from >> es[i].to >> es[i].cost;
	shortest_path(0);
	for(int i = 0; i < V; i++) cout << d[i] << " ";
	return 0;
}

堆优化

对迪杰斯特拉算法进行堆优化

要点:
利用优先队列,在更新最短距离时,把对应元素往根的方向移动以满足堆的性质
每次push都会push到适当的位置,保持堆的稳定,“排序为从小到大”,下次取时总会取出min

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<numeric> 
#define MAX_V 100
#define INF 0x3f3f3f3f
using namespace std;
struct edge{
	int to, cost;
}; 
typedef pair<int, int> P;//first为最短距离,second是顶点编号
int V, E;
//邻接表的vector表示法 
vector<edge> G[MAX_V];
int d[MAX_V];//d[i] 表示从 顶点s 到 顶点i 的最短距离 
void Shortest_Path(int s){
	//great<~>表示queue从小到大排列,而queue是队首出列,则是从小到大取出  
	priority_queue<P, vector<P>, greater<P> > que;
	fill(d, d+V, INF);
	d[s] = 0;
	que.push(P(0, s));
	while(!que.empty()){
		P p = que.top(); que.pop();
		//每次取出的是最小值 
		int v = p.second;
		if(d[v] < p.first) continue;//通往v的最小值已经小于p.first 返回继续pop下一个 
		for(int i = 0; i < G[v].size(); i++){
			edge e = G[v][i];
			if(d[e.to] > d[v] + e.cost){//v即from 
				d[e.to] = d[v] + e.cost;
				que.push(P(d[e.to], e.to));
				/*
				在更新最短距离时,把对应元素往根的方向移动以满足堆的性质
				每次push都会push到适当的位置,保持堆的稳定,"排序为从小到大",下次取时总会取出min 
				*/ 
			}
		}
	} 
} 
int main(){
	cin >> V >> E;
	for(int i = 0; i < E; i++){
		int v1, v2, w;
		edge e1, e2;
		cin >> v1 >> v2 >> w;
		e1.to = v2; e1.cost = w;
		e2.to = v1; e2.cost = w;
		G[v1].push_back(e1);
		G[v2].push_back(e2);
	}
	Shortest_Path(0);
	for(int i = 0; i < V; i++) cout << d[i] << " ";
	return 0;
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页