题目描述
题目链接:P4779 【模板】单源最短路径(标准版)
给定一个 n个点,m 条有向边的带非负权图,请你计算从 s 出发到每个点的距离。
数据保证你能从 s 出发到任意点。
输入格式
第一行为三个正整数 n,m,s 第二行起 m行,每行三个非负整数
u
i
,
v
i
,
w
i
u_{i},v_{i},w_{i}
ui,vi,wi表示从
u
i
u_{i}
ui 到
v
i
v_{i}
vi 有一条权值为
w
i
w_i
wi的有向边。
输出格式
输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。
输入输出样例
输入
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出
0 2 4 3
说明/提示
样例解释请参考 数据随机的模板题。
1
≤
n
≤
1
0
5
1≤n≤10^5
1≤n≤105,
1
≤
m
≤
2
×
1
0
5
1≤m≤2×10^5
1≤m≤2×105
s
=
1
s=1
s=1,
1
≤
u
i
,
v
i
≤
n
1≤u_i,v_i≤n
1≤ui,vi≤n,
0
≤
w
i
≤
1
0
9
0≤w_i≤10^9
0≤wi≤109
0
≤
∑
w
i
≤
1
0
9
0≤∑w_i≤10^9
0≤∑wi≤109
dijkstra算法C++代码
//C++ 代码
//采用堆优化的dijksra解法
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e5+100,M=2e5+100,inf=0x3f3f3f3f;
struct edge{
int u;
int v;
int w;
int next;
}e[M];
int head[N],cnt=0;
void Insert(int u,int v,int w){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
}
struct node{
int u; //节点u
int dis; //节点u与源点的距离
bool operator < (const node &a) const{
return dis>a.dis; //距离dis小的优先出队
}
};
int vis[N],dist[N]; //vis[u]为1表示u已经在“最短路已经确定”的集合中了
void dijstra(int n,int start){
memset(vis,0,sizeof(vis));
memset(dist,inf,sizeof(dist));
priority_queue<node>q;
q.push((node){start,0}); //起点入队
dist[start]=0;
node temp;
while(!q.empty()){
temp=q.top();
q.pop();
int u=temp.u;
//vis[u]==1则已经用u更新过最短路,且u已经不能松弛其它路径了(u的最短路已经确定)
if(vis[u]) continue;
vis[u]=1; //将u设为最短路已经确定
for(int i=head[u];i>=0;i=e[i].next){
int v=e[i].v;
int w=e[i].w;
if(dist[v]>dist[u]+w){
dist[v]=dist[u]+w;
q.push((node){v,dist[v]});
}
}
}
}
int main(){
memset(head,-1,sizeof(head));
int n,m,s;
scanf("%d%d%d",&n,&m,&s);
int u,v,w;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
Insert(u,v,w);
}
dijstra(n,s);
for(int i=1;i<=n;i++) printf("%d ",dist[i]);
return 0;
}