算法模板:spfa
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<set> #include<queue> #include<vector> using namespace std; const int inf=0x7f7f7f7f; const int NUM_NODE=310; struct edge{ // 边的数据结构 int to;int weight; edge(int t,int w):to(t),weight(w){} }; vector<edge> e[NUM_NODE]; int dist[NUM_NODE]; bool spfa(int s){ // s是源点 memset(dist,inf,sizeof(dist)); // 距离初始化为正无穷 dist[s]=0; // 源点到自己距离为0 bool inqueue[NUM_NODE]; // 用来记录顶点是否入队 memset(inqueue,0,sizeof(inqueue)); int qtimes[NUM_NODE]; // 用来记录入队次数 memset(qtimes,0,sizeof(qtimes)); queue<int> q; q.push(s);inqueue[s]=true;++qtimes[s]; // 将源点入队 int cur; while(!q.empty()){ // while队列非空 cur=q.front();q.pop();inqueue[cur]=false; // 取出队首 for(edge i:e[cur]) // 对每一个队首邻接的顶点 if(dist[i.to]>dist[cur]+i.weight){ // 如果经过队首会让你更近一些 dist[i.to]=dist[cur]+i.weight; // 那么就更新距离 if(!inqueue[i.to]){ q.push(i.to);inqueue[i.to]=true;++qtimes[i.to]; // 入队 if(qtimes[i.to]>NUM_NODE)return false; // 入队次数>顶点数,出现负环 } } } return true; // 没有负环 } int main(){ ios::sync_with_stdio(false); } /* SPFA可以处理负边,在稠密图里不如dijkstra。 复杂度是O(kE),k是每个点的平均进队次数。 1. 初始时,只有起点在队列中。 2. 遍历与起点相连的边,如果可以松弛就更新距离dist[],然后判断这个点在不在队列里,如果不在就入队标记。 3. 取出队首,取消标记,循环2-3步,直至队为空。 如何判断成环: 在储存边时,记录下每个点的入度,每个点入队的时候记录一次。 如果入队的次数大于这个点的入度,说明从某一条路进入了两次,即该点处成环。 如何判断负环: 一条最短路径最多通过所有顶点,即松弛n次,不可能从某些顶点绕好几圈。 因此,如果某个节点入队次数>n,则出现负环。 */
本文作者:MoonOut
本文链接:https://www.cnblogs.com/moonout/p/15411917.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步