dijkstra--非负权值的单源最短路径STL实现(邻接表+优先队列) (带路径)

一、预备知识:

用优先队列做大小根堆

注意:是非负权值的单源最短路径的STL实现,权值是负的不能用dijkstra算法
在这里插入图片描述
解释在第一段

二、代码:

#include<iostream>
#include<cstdio>
#include<list>
#include<queue>
#include<set>
#define INF 9999999

using namespace std;

class Graph
{
	int n;
	list<pair<int,double> > *adj;//邻接表 
public:
	Graph(int _n)
	{
		n = _n;
		adj = new list<pair<int, double> >[_n];
	}
	void addEdge(int u, int v, double weight)
	{
		adj[u].push_back(make_pair(v,weight)); 
	}
	void shortestPath(int src); 
};  
void Graph::shortestPath(int src)
{
	//用优先队列当小根堆,pair排序时先按first升序排,相等再按second升序排
	//因要按weight来排序,所以把weight放前面
	priority_queue< pair<double,int>,
				   	vector<pair<double,int> >,
				   	greater<pair<double,int> > > pq;  
				   
	vector<double>dist(n,INF);
	vector<int>parent(n,-1);	//parent[v] = u,由u到v
	vector<double>weights(n,INF);//weights[v]记录从src到v分支上某点到v的最小权值 
	pq.push(make_pair(0,src));
	dist[src] = 0;
	parent[src] = 0;
	weights[src] = 0;
	while(!pq.empty())
	{
		int u = pq.top().second;
		pq.pop();
		
		list<pair<int,double> >::iterator it;
		for(it = adj[u].begin(); it != adj[u].end(); it++)
		{
			int v = it->first;			 //获取顶点 
			double weight = it->second;	 //获取weight 
			
			if(dist[v] > dist[u]+weight)    
			{
				dist[v] = dist[u] + weight;
				pq.push(make_pair(dist[v],v));
				parent[v] = u;			//记录从哪到v最短 
				weights[v] = weight;	//记录到v的那条路径的路径 
			}
		}
	} 

	for(int i = 0 ;i < n; i++)
	{
		cout<<parent[i]<<"->"<<i<<" dist["<<i<<"]: "<<dist[i]
			<<" \t the weight "<<"from "<<parent[i]<<" to "<<i<<" is "<<weights[i]<<endl;  
	}
}
int main() 
{ 
    int V = 9; 
    Graph g(V); 
   
    g.addEdge(0, 1, 4); 
    g.addEdge(0, 7, 8); 
    g.addEdge(1, 2, 8); 
    g.addEdge(1, 7, 11); 
    g.addEdge(2, 3, 7); 
    g.addEdge(2, 8, 2); 
    g.addEdge(2, 5, 4); 
    g.addEdge(3, 4, 9); 
    g.addEdge(3, 5, 14); 
    g.addEdge(4, 5, 10); 
    g.addEdge(5, 6, 2); 
    g.addEdge(6, 7, 1); 
    g.addEdge(6, 8, 6); 
    g.addEdge(7, 8, 7); 
  
    g.shortestPath(0); 
  
    return 0; 
} 

在这里插入图片描述


注:事实上路径已经用双亲表示的树(parent数组)表示了,所以想要打印出树来也是可以的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值