# 【模板】单源最短路径(弱化版)
## 题目背景
本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 [P4779](https://www.luogu.org/problemnew/show/P4779)。
## 题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
## 输入格式
第一行包含三个整数 $n,m,s$,分别表示点的个数、有向边的个数、出发点的编号。
接下来 $m$ 行每行包含三个整数 $u,v,w$,表示一条 $u \to v$ 的,长度为 $w$ 的边。
## 输出格式
输出一行 $n$ 个整数,第 $i$ 个表示 $s$ 到第 $i$ 个点的最短路径,若不能到达则输出 $2^{31}-1$。
## 样例 #1
### 样例输入 #1
```
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
```### 样例输出 #1
```
0 2 4 3
```## 提示
【数据范围】
对于 $20\%$ 的数据:$1\le n \le 5$,$1\le m \le 15$;
对于 $40\%$ 的数据:$1\le n \le 100$,$1\le m \le 10^4$;
对于 $70\%$ 的数据:$1\le n \le 1000$,$1\le m \le 10^5$;
对于 $100\%$ 的数据:$1 \le n \le 10^4$,$1\le m \le 5\times 10^5$,$1\le u,v\le n$,$w\ge 0$,$\sum w< 2^{31}$,保证数据随机。**Update 2022/07/29:两个点之间可能有多条边,敬请注意。**
对于真正 $100\%$ 的数据,请移步 [P4779](https://www.luogu.org/problemnew/show/P4779)。请注意,该题与本题数据范围略有不同。
样例说明:![](https://cdn.luogu.com.cn/upload/pic/7641.png)
图片1到3和1到4的文字位置调换
1.这一题是最短路径,我写的是dijkstra算法,因为floyd可能会TLE。
2.可以看这个:https://blog.csdn.net/lxh0113/article/details/128200978?spm=1001.2014.3001.5502
上面是我先前写的关于dijkstra算法的核心思想。
3.dijkstra算法就是每次选择距离最短路径的最短的那一个点取扩展,去松弛每一条边,保留最小值。然后就可以得到一条每一个点距离起始点都是最短路径的数组。这个有点像动态规划。
代码如下:
#include<stdio.h>
#define N 100010
#define M 200010
const int INF=2147483647;
struct node
{
int to;
int w;
int next;
}edges[M];
int dij[N];
int book[N],head[M];
int n,m,s;
int min(int a,int b)
{
if(a>b) return b;
return a;
}
int dijk()
{
int i,j,tree=1,y;
dij[s]=0;book[s]=1;
y=s;
while(tree<n)
{
//先刷新起点能去的值
for(i=head[y];i!=0;i=edges[i].next)
{
dij[edges[i].to]=min(dij[edges[i].to],dij[y]+edges[i].w);
// printf(" y %d to %d dij-to %d\n",y,edges[i].to,dij[edges[i].to]);
}
//找到接下来最小的点
for(i=1;i<=n&&book[i]==1;i++);
j=i;
for(i++;i<=n;i++)
{
if(dij[i]<dij[j]&&book[i]==0)
{
j=i;
}
}
//找到之后
book[j]=1;
y=j;
tree++;//确定了一个值
}
for(i=1;i<=n;i++)
printf("%d ",dij[i]);
}
int main()
{
int i,j,u,v,w;
scanf("%d%d%d",&n,&m,&s);
for(i=1;i<=n;i++)
{
dij[i]=INF;
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
edges[i].to=v;
edges[i].w=w;
edges[i].next=head[u];
head[u]=i;
}
dijk();
return 0;
}