题目描述
给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入
第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。
接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度(长度不会超过100)。
输出
一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为-1)
样例输入
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
提示
N<=1000,M<=100000
对于100%的数据:N<=10000,M<=500000
代码
#pragma GCC optimize(1) #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #include<bits/stdc++.h> #define rep(i,j,k) for(register int i=(j);i<=(k);++i) using namespace std; template<class T> inline void read(T &x) { x=0; register char c=getchar(); register bool f=0; while(!isdigit(c))f^=c=='-',c=getchar(); while(isdigit(c))x=x*10+c-'0',c=getchar(); if(f)x=-x; } const int N = 10001; const int M = 500001; int n, m, s; struct node{ int a,b,c; }g[M]; int dis[N]; bool flag[N]; inline bool cmp(const node &x,const node &y) { return x.a<y.a; } int f[N], e[N]; int main() { read(n), read(m), read(s); rep(i, 1, m) read(g[i].a), read(g[i].b), read(g[i].c); sort(g+1,g+1+m,cmp); memset(dis,-1,sizeof(dis)); f[g[1].a]=1; rep(i,2,m) if(g[i].a!=g[i-1].a) { e[g[i-1].a]=i-1; f[g[i].a]=i; } e[g[m].a]=m; dis[s]=0; register int num=0; while(num<n) { register int mn=-1,u=-1; rep(i,1,n) if(flag[i]==0&&dis[i]!=-1) if(dis[i]<mn||mn==-1) mn=dis[i],u=i; if(u==-1) break; flag[u]=1; num++; rep(i,f[u],e[u]) if(i==0) break; else { register int v=g[i].b,val=g[i].c; if(dis[v]==-1||dis[v]>dis[u]+val) dis[v]=dis[u]+val; } } rep(i,1,n) printf("%d ",dis[i]); return 0; }