描述
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
输入
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
输出
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从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<bits/stdc++.h> #define LL long long int #define INIT(a,b) memset(a,b,sizeof(a)) #define rep(i,a,b) for(int i=a;i<b;i++) #define per(i,b,a) for(int i=b-1;i>=a;i--)
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<Edge> 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<Node[now].size();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<M;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<<dis[T]<<endl; } return 0; }
|