题目背景
本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779。
题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入格式
第一行包含三个整数 �,�,�n,m,s,分别表示点的个数、有向边的个数、出发点的编号。
接下来 �m 行每行包含三个整数 �,�,�u,v,w,表示一条 �→�u→v 的,长度为 �w 的边。
输出格式
输出一行 �n 个整数,第 �i 个表示 �s 到第 �i 个点的最短路径,若不能到达则输出 231−1231−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
代码:
#include<stdio.h>
struct node{
int u,v,w;//u,此边子节点;v,与最近父节点一样边的编号,w此边的权值
}e[1000000];//代表领接表
long long ans[1000000];
int head[100000],cnt,m,n,s;//head以某点为父节点引出最后一条边
bool book[1000000];
void edge(int x,int y,int z)//建领接表 ,起点,终点,权值
{
e[++cnt].u=y;//更新cnt
e[cnt].w=z;
e[cnt].v=head[x];
head[x]=cnt;
}
main()
{
scanf("%d %d %d",&n,&m,&s);
for(int i=1;i<=n;i++)
ans[i]=2147483647;
ans[s]=0;
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
edge(a,b,c);
}
int pos=s;
while(book[pos]==0)//表搜完整个图
{
long long minn=2147483647;
book[pos]=1;
for(int i=head[pos];i!=0;i=e[i].v)//链式搜边
{
if(!book[e[i].u]&&ans[e[i].u]>ans[pos]+e[i].w)
{
ans[e[i].u]=ans[pos]+e[i].w;//更新
}
}
for(int i=1;i<=n;i++)
{
if(ans[i]<minn&&book[i]==0)//取新最小值
{
minn=ans[i];
pos=i;
}
}
}
for(int i=1;i<=n;i++)
{
printf("%d ",ans[i]);
}
}