最短路算法模板

首先是Dijkstra算法,Dijkstra算法适用于边权为正的情况,它可用于计算正权图上的单源最短路,即从单个源点出发,到所有结点的最短路,该算法同时适用于有向图和无向图。给出代码的时间复杂度为O(mlogn),m为边的数目,n为点的数目。

struct Edge{
	int from,to,dist; //从点from到to点距离dist 
	Edge(int u,int v,int d):from(u),to(v),dist(d){} //初始化边 
}; 

struct HeapNode{ 
	int d,u; //d为从s点到u点的的距离 
	bool operator < (const HeapNode& rhs) const{
		return d > rhs.d;  //定义最小堆 
	}
};
//把该算法用到的数据结构封装到一个结构体中 
struct Dijkstra{
	
	int n,m;
	vector edges;
	vector G[maxn];
	bool done[maxn];  //是否已永久标号 
	int d[maxn];      //s到各个点的距离 
	int p[maxn];      //最短路中的上一条弧 
	
	//初始化 
	void init(int n){ 
		this -> n = n;
		for(int i = 0; i < n; i++){
			G[i].clear();
		}
		edges.clear();
	}
	
	//添加边 
	void AddEdge(int from,int to,int dist){
		edges.push_back(Edge(from,to,dist));
		m = edges.size();
		G[from].push_back(m - 1);
	}
	
	//主体算法 
	void dijkstra(int s){
		priority_queue Q;
		for(int i = 0; i < n; i++){
			d[i] = INF;
		}
		d[s] = 0;
		memset(done,0,sizeof(done));
		Q.push((HeapNode){0,s});
		while(!Q.empty()){
			HeapNode x = Q.top();
			Q.pop();
			int u = x.u;
			//避免重复扩展 
			if(done[u]){
				continue;
			}
			done[u] = true;
			for(int i = 0; i < G[u].size(); i++){
				Edge& e = edges[G[u][i]];
				//松弛操作 
				if(d[e.to] > d[u] + e.dist){
					d[e.to] = d[u] + e.dist;
				    p[e.to] = G[u][i]; 
					Q.push((HeapNode){d[e.to],e.to});
				}
			}
		}
	}
	
}dij;

接下来是spfa算法,也是求单源最短路,该算法解决了Dijkstra算法不能解决负边权的问题,该算法还有一个功能,就是判断一个图是否含有负圈。时间复杂度最坏是O(mn),不过在实践中,往往只需要很短的时间就能求出最短路,这个算法其实还有几个优化。

struct Edge{
	int from,to,dist; //从点from到to点距离dist 
	Edge(int u,int v,int d):from(u),to(v),dist(d){} //初始化边 
}; 
//把该算法用到的数据结构封装到一个结构体中 
struct SPFA{
	
	int n,m;
	vector edges;
	vector G[maxn];
	bool inq[maxn];
	int d[maxn];
	int p[maxn];
	int cnt[maxn];
	
	void init(int n){
		this -> n = n;
		for(int i = 0; i < n; i++){
			G[i].clear();
		}
		edges.clear();
	}
	
	void AddEdge(int from,int to,int dist){
		edges.push_back(Edge(from,to,dist));
		m = edges.size();
		G[from].push_back(m - 1);
	}
	
	bool spfa(int s){
		queue Q;
		for(int i = 0; i < n; i++){
			d[i] = INF;
			cnt[i] = 0;
			inq[i] = 0;
		}
		d[s] = 0;
		Q.push(s);
		inq[s] = true;
		
		while(!Q.empty()){
			int u = Q.front();
			Q.pop();
			
			inq[u] = false;
			for(int i = 0; i < G[u].size(); i++){
				Edge& e = edges[G[u][i]];
				if(d[u] < INF && d[e.to] > d[u] + e.dist){
					d[e.to] = d[u] + e.dist;
					p[e.to] = G[u][i];
					
					if(!inq[e.to]){
						Q.push(e.to);
						inq[e.to] = true;
						if(++cnt[e.to] > n){
							return  false;
						}
					}
				}
			}
		}
		return true;
	}
}sp; 

然后就是Floyd算法,求任意两点之间的最短路

for(int i = 1; i <= n; i++){
	for(int j = 1; j <= n; j++){
		if(i == j){
			mp[i][j] = 0;
		}
		else{
			mp[i][j] = INF;
		}
	}
}
for(k = 1; k <= n; k++){
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			if(d[i][j] < INF && d[k][j] < INF){
				d[i][j] = min(d[i][j],d[i][k] + d[k][j]);
			} 
		}
	}
}


你可能感兴趣的:(ACM-图论)