问题描述
给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。
输入格式
第一行两个整数n, m。
接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。
输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。
题解: 前向星 存图 SPFA
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<map> 5 #include<queue> 6 using namespace std; 7 struct node 8 { 9 int next; 10 int to; 11 int we; 12 } edge[200005]; 13 int nedge=0; 14 int pre[20005],vis[20005],d[20005]; 15 int n,m; 16 int aa,bb,cc; 17 int now; 18 queue<int>q; 19 void add (int a,int b ,int c) 20 { 21 nedge++; 22 edge[nedge].to=b; 23 edge[nedge].we=c; 24 edge[nedge].next=pre[a]; 25 pre[a]=nedge; 26 } 27 void spfa() 28 { 29 for(int i=1;i<=n;i++) 30 { 31 vis[i]=0; 32 d[i]=0xfffffff; 33 } 34 q.push(1); 35 vis[1]=1; 36 d[1]=0; 37 while(!q.empty()) 38 { 39 now=q.front(); 40 q.pop(); 41 vis[now]=0; 42 for(int i=pre[now];i!=0;i=edge[i].next) 43 { 44 int mm=edge[i].to; 45 if(d[now]+edge[i].we<d[mm]) 46 { 47 d[mm]=d[now]+edge[i].we; 48 if(!vis[mm]) 49 { 50 vis[mm]=1; 51 q.push(mm); 52 } 53 } 54 } 55 } 56 } 57 int main() 58 { 59 scanf("%d %d",&n,&m); 60 for(int i=1;i<=n;i++) 61 { 62 pre[i]=0; 63 } 64 memset(edge,0,sizeof(edge)); 65 for(int i=1;i<=m;i++) 66 { 67 scanf("%d %d %d",&aa,&bb,&cc); 68 add(aa,bb,cc); 69 } 70 spfa(); 71 for(int i=2;i<=n;i++) 72 printf("%d ",d[i]); 73 return 0; 74 }