给定一个 NN 个点,MM 条有向边的带非负权图,请你计算从 SS 出发,到每个点的距离。
数据保证你能从 SS 出发到任意点。
第一行为三个正整数 N, M, S。 第二行起 MM 行,每行三个非负整数 ui,vi,w,表示从 ui到 vi有一条权值为 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≤100000;
1≤M≤200000;
S=1;
1≤ui,vi ≤N;
wi ≤10^9 ,
0≤∑wi≤10^9 。
简单的单源最短路模板题 直接上板子就完事了
//https://www.luogu.org/problem/P4779
#include<map>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
LL read()
{
LL x=0,w=1;
char ch=0;
while(ch<'0'||ch>'9')
{
if(ch=='-')
{
w=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return w*x;
}
int n,m,s;
int ui,vi,wi;
int cnt,head[100005],d[100005];
struct node{
int to,next,w;
};
node edge[200005];
void add(int x,int y,int w)
{
edge[++cnt].to=y;
edge[cnt].next=head[x];
edge[cnt].w=w;
head[x]=cnt;
}
struct nn{
int x,dis;
bool operator <(const nn& b)const//重载运算符'<'
{
return dis>b.dis;//顺序按照dis从小到大排(此处与sort的cmp恰好相反)
}
};//记录入队的节点和距离
priority_queue < nn > q;
inline nn init(int xx,int dd)
{
nn t;
t.x=xx;
t.dis=dd;
return t;
}
nn now;
void dij(int s)
{
for(register int i=1;i<=n;i++)//初始化
{
d[i]=INF;
}
d[s]=0;//d[x]代表点s到 x的距离
now.x=s;
now.dis=0;
q.push(now);
while(!q.empty())
{
now=q.top();
q.pop();
if(now.dis>d[now.x])//优化 如果该边权大于到点now.x的距离 说明该边比已有点更差就没有必要去遍历该点了
continue ;
for(register int i=head[now.x];i!=0;i=edge[i].next)//遍历当前now点所连接的所有边
{
if(d[edge[i].to]>d[now.x]+edge[i].w)//如果该边比已有点更优 则对该边所连的点进行松弛,并将该点入列
{
d[edge[i].to]=d[now.x]+edge[i].w;
q.push(init(edge[i].to,d[edge[i].to]));
}
}
}
}
int main()
{
n=read();
m=read();
s=read();
for(register int i=1;i<=m;i++)
{
ui=read();
vi=read();
wi=read();
add(ui,vi,wi);
}
dij(1);
for(register int i=1;i<=n;i++)
{
cout<<d[i]<<' ';
}
return 0;
}