问题描述

给定一个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
数据规模与约定

对于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\n",d[i]);
73     return 0;
74 }
View Code