洛谷P3385 负环与SPFA算法
Posted 专吃小仙女
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3385 负环与SPFA算法相关的知识,希望对你有一定的参考价值。
SPFA算法:
SPFA算法是图论中主要应用于解决带负权图相关问题的一种算法,它死了。
时间复杂度:O(ke)//k为平均每个节点入队次数
算法思路:
1,建立先进先出队列存放待优化结点;
2,每次去除当前队首结点u,用u最短路径估计值将与u相连的结点v进行松弛操作,若v最短路径被更新且v不在队列中,将v加入队尾;
(松弛操作:对,每个集合中的节点v,都设置dis[v]表示起点与v间最短路径权值的上界的操作
3,重复上述操作直至队列为空。
于是板子题又双叒叕应运而生:https://www.luogu.com.cn/problem/P3385
#include<bits/stdc++.h> #define ff(i,s,e) for(int i=s;i<=e;i++) #define fff(i,s,e) for(int i=s;i>=e;i--) using namespace std; inline int read() int x=0,f=1; char ch=getchar(); while(ch<\'0\'||ch>\'9\')if(ch == \'-\') f=-1 ; ch=getchar(); while(ch>=\'0\'&&ch<=\'9\')x=(x<<1)+(x<<3)+(ch^48) ; ch=getchar(); return x*f; const int N=2010,M=3010,inf=0x3f3f3f3f; int n,m; int tal,head[N]; int dis[N]; int mark[N];//元素i被标记过几次 bool vis[N];//元素i是否在队列中 struct qwq int to,nxt,w; a[M*2]; queue<int> q; void add(int u,int v,int w)//链式前向星存储 a[++tal].w=w; a[tal].to=v; a[tal].nxt=head[u]; head[u]=tal; bool spf() ff(i,1,n) dis[i]=inf,vis[i]=0,mark[i]=0;//预处理 while(!q.empty()) q.pop();//清空队列 q.push(1);//将起点加入队列 dis[1]=0,vis[1]=1,mark[1]++; while(!q.empty()) int u=q.front();//取出队首元素 q.pop(); vis[u]=0;//标记队首出队 for(int i=head[u];i;i=a[i].nxt)//枚举u可到达的所有结点 int v=a[i].to; if(dis[v]>dis[u]+a[i].w)//若以u为中转结点更优,更新 dis[v]=dis[u]+a[i].w; if(!vis[v])//若v不在队列,将其加入 vis[v]=1,mark[v]++;q.push(v); if(mark[v]>=n) return 1;//判断负环,可由松弛原理推导 return 0; int main() int T=read(),u,v,w; while(T--) n=read(),m=read(); tal=0; memset(head,-1,sizeof(head));//初始化 ff(i,1,m) u=read(),v=read(),w=read(); add(u,v,w); if(w>=0) add(v,u,w); if(spf()) printf("YES\\n"); else printf("NO\\n"); return 0;
阿巴阿巴
以上是关于洛谷P3385 负环与SPFA算法的主要内容,如果未能解决你的问题,请参考以下文章