spfa作为图论中的常用算法,深受各类出题人和各位OIer的喜爱;
so,为了给大众创造福利,宝宝在此奉上spfa大发的思路和模板;以感谢社会,
感谢CCF,感谢CCTV,
感谢我的老师,感谢同学们,
感谢noi,感谢noip,感谢ioi,
感谢不辞辛劳的学长学姐,
感谢帮我改程序,被我烦死的xxy ~QAQ~······and so on;
程序和图解做得比较难看,就请大家见谅了!!~(≧▽≦)/~ 谢啦!!☆⌒(*^-゜)v
思路:见程序
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int v,x,y,n; int head[100000],num,m,dis[1000]; bool vis[10000]; struct nond { int pre,v,to,from; //pre指这条边的上一条边,v指这条边的边权,to指这条边的终点,from至这条边的终点; }e[100000];//边表存储,减少空间占用; queue<int>q;//队列存储所能更新的点; void put(int from,int to,int v) { e[++num].pre=head[from]; e[num].from=from;// e[num].to=to; e[num].v=v//;这三句很好理解不解释 head[from]=num; }//边表的读入函数; /*重点解释一下对于改变的上一条边的存储, 看程序下的图片详解,在此不进行解释;*/ void spfa(int s) { q.push(s);//把s放入队列中; vis[s]=1;//把节点s标记为使用中; int point=s;//用point去更新所有与point相连的节点的最短距离; while(!q.empty())//如果队列不为空,说明有节点能去更新其他节点; { point=q.front();//记录队列中的第一个节点去更行其他节点; q.pop();//队列中的第一个节点已被使用,弹出; vis[point]=0;//该节点被弹出了队列,变为未被访问,未被使用; for(int i=head[point];i;i=e[i].pre)//以该节点去更新其他节点 { if(dis[e[i].from]+e[i].v<dis[e[i].to])//自己理解,不解释 { dis[e[i].to]=dis[e[i].from]+e[i].v; q.push(e[i].to); //节点i的最短距被更新过,说明i又可以去更新其他节点,把i读入队列; vis[e[i].to]=1;//标记为使用中; } } } } int main() { cin>>n>>m;//n节点个数,m是边的个数; memset(dis,127/3,sizeof(dis)); dis[1]=0;//dis存储到第i个点的最短路的长度; for(int i=1;i<=m;i++){ cin>>x>>y>>v;//x,y,v分别是相连边的起点~终点~长度; put(x,y,v);//向边表里加入边 put(y,x,v);//因为是无向图,所以加入两次; } spfa(1);//spfa搜索!!!这是重点!注意了~(≧▽≦)/~ for(int i=1;i<=n;i++) cout<<dis[i]<<" "; }
如果对你有所帮助,别忘了加好评哦;么么哒!!下次见!88