记得第一次接触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