最短路——SPFA

传送门HDU1874

描述

某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

输入

本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B再接下一行有两个整数S,T(0<=S,T

输出

对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.

样例

  • Input
    3 3
    0 1 1
    0 2 3
    1 2 1
    0 2
    3 1
    0 1 1
    1 2
  • Output
    2
    -1

题解

  • spfa——设立一个先进先出的队列q用来保存待优化的结点,优化时每次取出队首结点u,通过该点的每一条边对下一个点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
    松弛操作的原理是著名的定理:“三角形两边之和大于第三边”,在信息学中我们叫它三角不等式。所谓对结点i,j进行松弛,就是判定是否dis[j]>dis[i]+w[i,j],如果该式成立则将dis[j]减小到dis[i]+w[i,j],否则不动。
  • 和广搜bfs的区别:
    SPFA 在形式上和广度(宽度)优先搜索非常类似,不同的是bfs中一个点出了队列就不可能重新进入队列,但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进(重新入队),于是再次用来改进其它的点,这样反复迭代下去。
  • 存储方式——邻接表

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include
#define LL long long int
#define INIT(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i
#define per(i,b,a) for(int i=b-1;i>=a;i--)
//b——0,-1,128,0x3f,127 ,字符
const double Pi = acos(-1);
const double E = exp(1.0);
const LL mod =1e9+7;
const int MAX=0x7fffffff;
const int MIN=-0x7fffffff;
const int INF=0x3f3f3f3f;
using namespace std;
typedef struct{
int next;
int weigh;
}Edge;
int N,M;
vector Node[220];
int dis[220];bool used[220];
void spfa(int a)
{
for(int i=0;i<220;i++){dis[i]=INF;used[i]=false;}
queue<int> Road;
used[a]=true;Road.push(a);dis[a]=0;
while(!Road.empty()){
int now=Road.front();used[now]=false;Road.pop();
for(int i=0;i
if(dis[Node[now][i].next]>dis[now]+Node[now][i].weigh){
dis[Node[now][i].next]=dis[now]+Node[now][i].weigh;
if(!used[Node[now][i].next]){
used[Node[now][i].next]=true;
Road.push(Node[now][i].next);
}
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
int a,b,w,S,T;
while(cin>>N>>M)
{
for(int i=0;i<220;i++)
Node[i].clear();
for(int i=0;i
cin>>a>>b>>w;
Edge Temp=(Edge){b,w};
Node[a].push_back(Temp);
Temp=(Edge){a,w} ;
Node[b].push_back(Temp);
}
cin>>S>>T;
spfa(S);
if(dis[T]==INF)cout<<"-1"<<endl;
else cout<endl;

}
return 0;
}

你可能感兴趣的:(最短路——SPFA)