基于贪心思想,只适用于边长为非负数的图
O(mlogn)
算法流程
1.初始化的dist[1]=0,其余节点的dist为正无穷
2.找出一个未被标记、dist[x]最小的节点x并标记
3.扫描x的所有出边(x,y,z),若dist[y]>dist[x]+z,则更新dist[y]
4.重复2、3,直到所有节点被标记
//by ziwan Catherine
//堆优化dijkstra 边长为非负数
//d[n]从起点到n的最短路
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=10010,M=1000010;
int head[N],ver[M],edge[M],next[M],d[N];
bool v[N];
int n,m,tot;
priority_queue< pair<int,int> > q;
//大根堆 优先队列 pair第一维为dist相反数(变成小根堆) 第二维为节点编号
void dijkstra(){
memset(d,0x3f,sizeof(d));
d[1]=0;//dist初始化 起点为0,其余为正无穷
memset(v,0,sizeof(v));//节点标记
q.push(make_pair(0,1));
while(q.size()){
int x=q.top().second;q.pop();//取堆顶
if(v[x]) continue;v[x]=1;
for(int i=head[x];i;i=next[i]){//扫描所有出边
int y=ver[i],z=edge[i];
if(d[y]>d[x]+z) {
d[y]=d[x]+z;
q.push(make_pair(-d[y],y));
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
ver[++tot]=y,edge[tot]=z;
next[tot]=head[x],head[x]=tot;
}//构建邻接矩阵
dijkstra();
for(int i=1;i<=n;i++)
cout<<d[i]<<endl;
return 0;
}