题目描述
给定一个 N 个点,M 条有向边的带非负权图,请你计算从 S 出发,到每个点的距离。
数据保证你能从 S 出发到任意点。
输入输出格式
输入格式:
第一行为三个正整数 N, M,S。 第二行起 M 行,每行三个非负整数 u_i, v_i, w_i,表示从 u_i 到 v_i 有一条权值为 w_i 的边。
输出格式:
输出一行 N 个空格分隔的非负整数,表示 S 到每个点的距离。
Input
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
output
0 2 4 3
算法 1:Dijkstra(入门写法)
代码
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int n,m,s,f[1001][1001],dis[1001]; bool vis[10001]; void dij() { memset(dis,0x3f,sizeof(dis)); dis[s]=0; for(int i=1;i<=n;++i) { int pos=0; for(int j=1;j<=n;++j) if(!vis[j] && dis[j]<dis[pos]) pos=j; vis[pos]=1; for(int j=1;j<=n;++j) { if(dis[pos]+f[pos][j]<dis[j]) dis[j]=dis[pos]+f[pos][j]; } } } int main() { memset(f,0x3f,sizeof(f)); scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;++i) { int from,to,val; scanf("%d%d%d",&from,&to,&val); f[from][to]=min(f[from][to],val); } dij(); for(int i=1;i<=n;++i) printf("%d ",dis[i]); return 0; }
算法 2:堆优化 Dijkstra
代码:
#include<stdio.h> #include<algorithm> #include<queue> using namespace std; const int MX=500010; struct Edge { int to,next,val; }edge[MX]; struct node { int pos,dis; }; priority_queue<node> q; bool operator<(const node &a,const node &b){ return a.dis>b.dis; } bool vis[MX]; int first[MX],dis[MX],cnt,n,m,s; void add(int from,int to,int val) { edge[++cnt].to=to; edge[cnt].val=val; edge[cnt].next=first[from]; first[from]=cnt; } void dij() { node st; st.pos=s,st.dis=0; q.push(st); while(!q.empty()) { node curr=q.top(); q.pop(); int from=curr.pos,val=curr.dis; if(vis[from]) continue; vis[from]=1; for(int i=first[from];i;i=edge[i].next) { int to=edge[i].to; if(val+edge[i].val<dis[to]) { dis[to]=val+edge[i].val; q.push((node){to,dis[to]}); } } } } int main() { scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;++i) { int from,to,val; scanf("%d%d%d",&from,&to,&val); add(from,to,val); } for(int i=1;i<=n;++i) dis[i]=2147483647; dis[s]=0; dij(); for(int i=1;i<=n;++i) printf("%d ",dis[i]); return 0; }