不被世界看好的SPFA依旧强势-HDU2680
记得第一次接触spfa是在高中的noip,那时候死记硬背过了pascal版本的优化之后的spfa。
当时的比赛还真用上了,因而水了个奖,毕竟学的不多,总共加起来学习pascal编程的时间不够7*24h。
看完了前情回顾,接下来就是见证奇迹的时刻,我要写spfa啦。
题目链接:HDU-2680
题目大意:一个人可以从多个起点开始出发,看到终点的最短路是多少。
题目分析:
1.如果我们把每个起点都spfa一次那么时间复杂度会加大很多。因而做个优化:设置一个0号位置,0号位置到每个起点都有一条路径,且这个路径的权重为0.这样,我们只需要从0号位置开始spfa一次就好啦。
2.选择邻接表存储图。(如果亲爱的读者大宝贝,邻接表忘记怎么实现的话,巴啦啦能量---->点我,我是邻接表的详解)
3.spfa模板。(其实不需要模板的,spfa和bfs差不多的,如果你忘了的话,巴啦啦能量×2---->点我,我是spfa未优化的模板)
所以实现如下:
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int MaxnEdge = 21010; const int MaxnV = 1010; const int INF = 0x3f3f3f3f; int n, m, s; int visit[MaxnV]; int dis[MaxnV]; int u[MaxnEdge], v[MaxnEdge], w[MaxnEdge]; int first[MaxnEdge], Next[MaxnEdge]; void spfa(int start){ memset(visit, 0, sizeof(visit)); memset(dis, 0x3f, sizeof(dis)); queue<int>q; while (!q.empty()) q.pop(); q.push(start); visit[start] = 1; dis[start] = 0; while (!q.empty()){ int now = q.front(); q.pop(); visit[now] = 0; for (int i = first[now]; i != -1; i = Next[i]){ if (dis[v[i]] > dis[now] + w[i]){ dis[v[i]] = dis[now] + w[i]; if (!visit[v[i]]){ q.push(v[i]); visit[v[i]] = 1; } } } } } int main(){ while (scanf("%d%d%d", &n, &m, &s)!= EOF){ memset(first, -1, sizeof(first)); memset(Next, -1, sizeof(first)); for (int i = 0; i < m; i++){ scanf("%d%d%d", &u[i], &v[i], &w[i]); Next[i] = first[u[i]]; first[u[i]] = i; } int ncase; scanf("%d", &ncase); for (int i = 0; i < ncase; i ++){ int to; scanf("%d", &to); v[i + m] = to; w[i + m] = 0; Next[i + m] = first[0]; first[0] = i + m; } spfa(0); if (dis[s] == INF){ printf("-1\n"); } else printf("%d\n", dis[s]); //for (int i = first[0]; i != -1; i = Next[i]) // printf("%d\%d\%d\n", u[i], v[i], w[i]); } return 0; }
细心的读者大宝贝,你一定发现了一些猫腻,那就是:
1.MaxnEdge = 21010;这是因为总边数=题目输入边数+与0号位置相连的边数。
2.Next数组的首字母大写了,为什么不是next数组呢?【强迫症如我】
原因是CE了,可能next在HDU的编译器上是关键字好像:
改成Next就AC了,奇怪而又有趣是吧:
3.在初始化dis数组的时候,要初始化最大值,const int INF=0x7fffffff;并不是最好的选择;最好的选择是const int INF = 0x3f3f3f3f;还可以用memset初始化:memset(dis, 0x3f, sizeof(dis));
附一下memset初始化的大佬解释:巴啦啦能量×3----->点我呀,我是memset我很皮
好了,昨天发现数据结构的网课TMD第五周的作业提交截止时间过了,很难受,所以今天没有表情包。
不过今天还是得皮一下:
沿着你皮肤纹理,走过曲折手臂
目光所及,是你发际
让我陷入这黑色的沼泽
心甘情愿地赴死
在你的瞳孔里看到自己的眼睛
在你的呼吸里找到自己的气息
在你的眉宇间闪躲自己的思念
在你的身体里找到另一个自己
我爱你
从左心房到右心室
从心脏到喉咙
从血液到灵魂
2018年4月17日晚0:10