D03 最短路 Bellman-Ford 算法 spfa 算法 P3385【模板】负环
视频链接:D03 最短路 Bellman-Ford 算法 SPFA 算法——信息学奥赛算法_哔哩哔哩_bilibili
//Ford 判负环 740ms
#include <cstring> #include <iostream> #include <algorithm> using namespace std; const int inf=0x3f3f3f3f; const int N=2010,M=6010; int n,m; int to[M],ne[M],w[M],h[N],tot; int d[N]; void add(int a,int b,int c){ to[++tot]=b;w[tot]=c; ne[tot]=h[a];h[a]=tot; } bool ford(){ memset(d,inf,sizeof d); d[1]=0; bool flag; //是否松弛 for(int i=1;i<=n;i++){ //跑n轮 flag=false; for(int u=1;u<=n;u++){ //n个点 if(d[u]==inf)continue; for(int j=h[u];j;j=ne[j]){ int v=to[j]; if(d[v]>d[u]+w[j]){ d[v]=d[u]+w[j]; flag=true; } } } if(!flag)break; } return flag; //第n轮=true,有负环 } int main(){ int T; scanf("%d",&T); while(T--){ tot=0; memset(h,0,sizeof(h)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); if(w>=0)add(v,u,w);; } puts(ford()?"YES":"NO"); } return 0; }
//BFS_spfa 判负环 530ms #include <iostream> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int inf=0x3f3f3f3f; const int N=2010,M=6010; int n,m; int to[M],ne[M],w[M],h[N],tot; int d[N],cnt[N],vis[N]; void add(int a,int b,int c){ to[++tot]=b;w[tot]=c; ne[tot]=h[a];h[a]=tot; } bool spfa(){ //判负环 memset(d,0x3f,sizeof d); memset(vis,0,sizeof vis); memset(cnt,0,sizeof cnt); queue<int>q; q.push(1); vis[1]=1; d[1]=0; while(q.size()){ int u=q.front();q.pop();vis[u]=0; for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(d[v]>d[u]+w[i]){ d[v]=d[u]+w[i]; cnt[v]=cnt[u]+1; if(cnt[v]>=n)return 1;//判边数 if(!vis[v])q.push(v),vis[v]=1; } } } return 0; } int main(){ int T; scanf("%d",&T); while(T--){ tot=0; memset(h,0,sizeof(h)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); if(w>=0)add(v,u,w);; } puts(spfa()?"YES":"NO"); } return 0; }
//BFS_spfa 判负环 690ms #include <iostream> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int inf=0x3f3f3f3f; const int N=2010,M=6010; int n,m; int to[M],ne[M],w[M],h[N],tot; int d[N],cnt[N],vis[N]; void add(int a,int b,int c){ to[++tot]=b;w[tot]=c; ne[tot]=h[a];h[a]=tot; } bool spfa(){ //判负环 memset(d,0x3f,sizeof d); memset(vis,0,sizeof vis); memset(cnt,0,sizeof cnt); queue<int>q; q.push(1); vis[1]=1; d[1]=0; while(q.size()){ int u=q.front();q.pop();vis[u]=0; for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(d[v]>d[u]+w[i]){ d[v]=d[u]+w[i]; if(++cnt[v]>n)return 1;//判点数 if(!vis[v])q.push(v),vis[v]=1; } } } return 0; } int main(){ int T; scanf("%d",&T); while(T--){ tot=0; memset(h,0,sizeof(h)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); if(w>=0)add(v,u,w);; } puts(spfa()?"YES":"NO"); } return 0; }
//DFS_spfa 判负环 会卡点 #9 #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int inf=0x3f3f3f3f; const int N=2010,M=6010; int n,m; int to[M],ne[M],w[M],h[N],tot; int d[N],vis[N]; void add(int a,int b,int c){ to[++tot]=b;w[tot]=c; ne[tot]=h[a];h[a]=tot; } bool spfa(int u){ //判负环 vis[u]=1; for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(d[v]>d[u]+w[i]){ d[v]=d[u]+w[i]; if(vis[v]||spfa(v))return 1; } } vis[u]=0; return 0; } int main(){ int T; scanf("%d",&T); while(T--){ tot=0; memset(h,0,sizeof(h)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); if(w>=0)add(v,u,w);; } memset(d,0x3f,sizeof d);d[1]=0; memset(vis,0,sizeof vis); puts(spfa(1)?"YES":"NO"); } return 0; }
分类:
D 图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!