Dijkstra(堆优化)

Dijkstra 算法 (模板)【堆优化】

传送门:

Dijkstra:建议先掌握原始版本

基本思路:用一个优先队列,priority queue来保存点到点之间的距离,优先队列自动把队列里的数据排序(这里需要手动写一个bool型函数来定义为由大到小排序),枚举各种可能的走法,包括当某两点之间的路线为无限大时,(所以可以自动处理重边,而原始版本的不能)最后把最小的方案(即dis)输出给d数组,标记一下,把剩余的方案全部pop出去(相同出发点和目标点的情况下,所以代码中有一句 if(vis[u]) continue;)。

注意:该模板已经使用STL里的容器,如果对此不熟悉的读者,请先自行百度搜索,我以后会贴出这方面的博客的。

OK,上代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 666666
using namespace std;
struct ed{int v,c;};//输入数据时vector使用,u代表起始点,v代表目标点,c代表这条边的权值; 
struct dn{int u,d;};//处理数据时使用,u代表目标点,d代表权值
vector<ed>g[10001];//注意,其实这里就已经是一个二维数组了,因为每一个vector数组就是一个一维数组
bool operator < (dn x,dn y){
	return x.d>y.d;
}                     //先出小的,就相当于普通算法中的遍历找最小 
int vis[100001],d[100001],n,m,k;
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;++i)
	d[i]=INF;      //初始化d数组,默认与各点距离为无限大 
	for(int i=1;i<=m;++i)
	{
		int u,v,c;
		scanf("%d%d%d",&u,&v,&c);
		g[u].push_back((ed){v,c});//输入数据,这里需注意题上给出的是单向路还是双
	}//                                 单向路 不用判断重边,重边的走法也考虑进了优先
	priority_queue<dn>q;//              队列
	q.push((dn){k,0});//将起始点放入堆中 
	while(!q.empty()){
		int u=q.top().u,v;
		double dis=q.top().d;
		q.pop();//弹出 
		if(vis[u]) continue;//点u已经用过的话,就跳过 
		vis[u]=1;//否则标记为1 
		d[u]=dis;//             struct dn{int u,d;}; 
		for(int i=0;i<g[u].size();i++)
		if(!vis[v=g[u][i].v])
		q.push((dn){v,d[u]+g[u][i].c}); //比较的事已经交给优先队列q了,不必纠结了
	}//                                       哈哈哈
	for(int i=1;i<=n;++i)
	cout<<d[i]<<" ";
	return 0;
}

我的QQ:1206668472

END


猜你喜欢

转载自blog.csdn.net/qq_36992525/article/details/79250323
今日推荐