首页 > 代码库 > hiho一下 第二十五周(SPFA)

hiho一下 第二十五周(SPFA)

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

万圣节的晚上,小Hi和小Ho在吃过晚饭之后,来到了一个巨大的鬼屋!

鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些道路连通,两个地点之间可能有多条道路连通,但是并不存在一条两端都是同一个地点的道路。

不过这个鬼屋虽然很大,但是其中的道路并不算多,所以小Hi还是希望能够知道从入口到出口的最短距离是多少?

提示:Super Programming Festival Algorithm。

输入

每个测试点(输入文件)有且仅有一组测试数据。

在一组测试数据中:

第1行为4个整数N、M、S、T,分别表示鬼屋中地点的个数和道路的条数,入口(也是一个地点)的编号,出口(同样也是一个地点)的编号。

接下来的M行,每行描述一条道路:其中的第i行为三个整数u_i, v_i, length_i,表明在编号为u_i的地点和编号为v_i的地点之间有一条长度为length_i的道路。

对于100%的数据,满足N<=10^5,M<=10^6, 1 <= length_i <= 10^3, 1 <= S, T <= N, 且S不等于T。

对于100%的数据,满足小Hi和小Ho总是有办法从入口通过地图上标注出来的道路到达出口。

输出

对于每组测试数据,输出一个整数Ans,表示那么小Hi和小Ho为了走出鬼屋至少要走的路程。

样例输入
5 10 3 51 2 9972 3 5053 4 1184 5 543 5 4803 4 7965 2 7942 5 1465 4 6042 5 63
样例输出
172
技术分享
 1 #include <iostream> 2 #include <cstdio> 3 #include <memory.h> 4 #include <string> 5 #include <vector> 6 #include <queue> 7 #include <set> 8 #include <map> 9 #include <algorithm>10 #include <climits>11 using namespace std;12 13 #define MAXN 11111114 #define MAX 111111115 struct node {16     int x,weight;17 };18 vector< node > mp[MAXN];19 int cost[MAX];  //存储到起始点的最近距离20 int n,m,s,e;21 22 bool spfa()23 {24     queue<node> q;25     cost[s] = 0;26     q.push({s,0});27     while (!q.empty())28     {29         node now = q.front();30         q.pop();31         if (cost[now.x] < now.weight) continue;32         else cost[now.x] = now.weight;33         for (int i = 0;i < mp[now.x].size();i++) {34             //如果未访问过或者距离可更新35             if (cost[mp[now.x][i].x] == -1 || cost[mp[now.x][i].x] > mp[now.x][i].weight + cost[now.x]) {36                 cost[mp[now.x][i].x] = mp[now.x][i].weight + cost[now.x];                                37                 q.push({mp[now.x][i].x,cost[mp[now.x][i].x]});38             }39 40         }41     }42     return true;43 }44 45 int main()46 {47     int a,b,w;48     memset(cost,-1,sizeof(cost));    //权值为-1表示还未访问过49     cin >> n >> m >> s >> e;50     for (int i = 0;i < m; ++ i)  {51         cin >> a >> b >> w;52         mp[a].push_back({b,w});53         mp[b].push_back({a,w});54     }55     if (spfa())56     cout << cost[e] << endl;57     return 0;58 }
代码君

 

 

另外附上大牛的SFPA代码

 

SPFA的两种写法,bfs和dfs,bfs判别负环不稳定,相当于限深度搜索,但是设置得好的话还是没问题的,dfs的话判断负环很快

技术分享
 1 int spfa_bfs(int s) 2 { 3     queue <int> q; 4     memset(d,0x3f,sizeof(d)); 5     d[s]=0; 6     memset(c,0,sizeof(c)); 7     memset(vis,0,sizeof(vis)); 8  9     q.push(s);  vis[s]=1; c[s]=1;10     //顶点入队vis要做标记,另外要统计顶点的入队次数11     int OK=1;12     while(!q.empty())13     {14         int x;15         x=q.front(); q.pop();  vis[x]=0;16         //队头元素出队,并且消除标记17         for(int k=f[x]; k!=0; k=nnext[k]) //遍历顶点x的邻接表18         {19             int y=v[k];20             if( d[x]+w[k] < d[y])21             {22                 d[y]=d[x]+w[k];  //松弛23                 if(!vis[y])  //顶点y不在队内24                 {25                     vis[y]=1;    //标记26                     c[y]++;      //统计次数27                     q.push(y);   //入队28                     if(c[y]>NN)  //超过入队次数上限,说明有负环29                         return OK=0;30                 }31             }32         }33     }34 35     return OK;36 37 }
BFS

 

技术分享
 1 int spfa_dfs(int u) 2 { 3     vis[u]=1; 4     for(int k=f[u]; k!=0; k=e[k].next) 5     { 6         int v=e[k].v,w=e[k].w; 7         if( d[u]+w < d[v] ) 8         { 9             d[v]=d[u]+w;10             if(!vis[v])11             {12                 if(spfa_dfs(v))13                     return 1;14             }15             else16                 return 1;17         }18     }19     vis[u]=0;20     return 0;21 }
DFS

 

hiho一下 第二十五周(SPFA)