P3385 【模板】负环
题目链接 https://www.luogu.com.cn/problem/P3385
SPFA还没学,先用Bellman-Ford。 //更SPFA——2022.5.2
注意第45行的特判,因为存在某点不连通的情况。(差点没要我命...)
Bellman-ford
放AC代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e6 + 1000; 4 int t,n,m; 5 int cnt; 6 long long dis[N]; 7 bool vis[N]; 8 9 struct Edge 10 { 11 int u,v,w; 12 } edge[N]; 13 14 void add(int u,int v,int w) 15 { 16 edge[++cnt]= {u,v,w}; 17 } 18 19 void addd(int u,int v,int w) 20 { 21 if(w<0) add(u,v,w); 22 if(w>=0) add(u,v,w),add(v,u,w); 23 } 24 25 bool bellman_ford() 26 { 27 for(int i=1; i<=n; i++) 28 { 29 dis[i]=INT_MAX; 30 } 31 dis[1]=0; 32 33 for(int i=1; i<n; i++) 34 { 35 for(int j=1; j<=cnt; j++) 36 { 37 if(dis[edge[j].u]!=INT_MAX && dis[edge[j].v]>dis[edge[j].u]+edge[j].w) 38 dis[edge[j].v]=dis[edge[j].u]+edge[j].w; 39 } 40 } 41 42 bool flag=1;//标记有无负环 43 for(int i=1; i<=cnt; i++) 44 { 45 if(dis[edge[i].u]==INT_MAX || dis[edge[i].v]==INT_MAX)//存在不连通的节点 46 continue; 47 if(dis[edge[i].v]>dis[edge[i].u]+edge[i].w)//松弛是否成功 48 { 49 flag=0;//成功则有负环 50 break; 51 } 52 } 53 return flag; 54 } 55 56 int main() 57 { 58 cin>>t; 59 while(t--) 60 { 61 cin>>n>>m; 62 cnt=0; 63 for(int i=1; i<=m; i++) 64 { 65 int u,v,w; 66 cin>>u>>v>>w; 67 addd(u,v,w); 68 } 69 if(bellman_ford()) 70 cout<<"NO"<<endl; 71 else 72 cout<<"YES"<<endl; 73 } 74 return 0; 75 }
SPFA
放AC代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2e3+10; 4 const int maxm = 6e3+10; 5 int t,n,m; 6 int tot; 7 int head[maxn]; 8 int dis[maxn]; 9 bool vis[maxn]; 10 int cnt[maxn];//表示1到i的最短路包含的边数 11 queue<int> q; 12 13 struct edge 14 { 15 int v,w,next; 16 } edge[maxm]; 17 18 void init() 19 { 20 for(int i=0;i<maxm;i++) edge[i].next=0; 21 for(int i=0;i<maxn;i++) head[i]=0; 22 tot=0; 23 } 24 25 void add(int u,int v,int w) 26 { 27 edge[++tot].v=v; 28 edge[tot].w=w; 29 edge[tot].next=head[u]; 30 head[u]=tot; 31 } 32 33 bool spfa() 34 { 35 memset(dis,0x3f,sizeof(dis)); 36 memset(vis,0,sizeof(vis)); 37 memset(cnt,0,sizeof(cnt)); 38 dis[1]=0; 39 vis[1]=true; 40 q.push(1); 41 while(!q.empty()) 42 { 43 int x=q.front(); 44 q.pop(); 45 vis[x]=false; 46 for(int i=head[x]; i!=0; i=edge[i].next) 47 { 48 int y=edge[i].v; 49 int z=edge[i].w; 50 if(dis[y]>dis[x]+z) 51 { 52 dis[y]=dis[x]+z;//更新最短路 53 cnt[y]=cnt[x]+1;//更新包含边数 54 if(cnt[y]>=n) return true; 55 if(!vis[y]) 56 { 57 q.push(y); 58 vis[y]=true; 59 } 60 } 61 } 62 } 63 return false; 64 } 65 66 int main() 67 { 68 cin>>t; 69 while(t--) 70 { 71 init(); 72 cin>>n>>m; 73 for(int i=1; i<=m; i++) 74 { 75 int u,v,w; 76 cin>>u>>v>>w; 77 add(u,v,w); 78 if(w>=0) add(v,u,w); 79 } 80 puts(spfa()?"YES":"NO"); 81 } 82 return 0; 83 }