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