Bellman-Ford、SPFA 判断负环
Bellman-Ford 负环
Bellman-Ford 会对边进行松弛操作,若不存在负环,则至多松弛 \(n-1\) 轮即可求出最短路,进而确定无负环。
-
注意需要特判
inf,因为负权。 -
注意需要
dis[s]=0。
vector 实现代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=2e3,inf=0x3f3f3f3f;
int n;
vector<pair<int,int>>g[N+1];
bool BellmanFord(){
static int dis[N+1];
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
for(int i=1;i<=n;i++){
bool flag=true;
for(int x=1;x<=n;x++){
if(dis[x]==inf){
continue;
}
for(auto [v,w]:g[x]){
if(dis[x]+w<dis[v]){
dis[v]=dis[x]+w;
flag=false;
}
}
}
if(flag){
return false;
}
}
return true;
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
int m;
cin>>n>>m;
for(int i=1;i<=n;i++){
g[i].resize(0);
}
while(m--){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back({v,w});
if(w>=0){
g[v].push_back({u,w});
}
}
if(BellmanFord()){
cout<<"YES\n";
}else{
cout<<"NO\n";
}
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
边集数组实现代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
const int N=2e3,M=3e3;
typedef long long ll;
int T,n,m,u,v,w,top;
struct edge{
int u,v;
ll w;
}a[2*M+1];
bool Bellman_Ford(int s){
static ll dis[N+1];
static bool flag;
for(int i=1;i<=n;i++)dis[i]=2147483647;
dis[s]=0;
for(int i=1;i<=n;i++){
flag=true;
for(int j=1;j<=top;j++){
if(dis[a[j].u]==2147483647)continue;
if(dis[a[j].u]+a[j].w<dis[a[j].v]){
dis[a[j].v]=dis[a[j].u]+a[j].w;
flag=false;
}
}
if(flag)break;
if(i==n)return true;
}return false;
}
void Start(){
top=0;
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
scanf("%d",&T);
while(T--){
Start();
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d %d %d",&u,&v,&w);
a[++top]={u,v,w};
if(w>=0)a[++top]={v,u,w};
}
printf("%s\n",(Bellman_Ford(1)?"YES":"NO"));
}
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
SPFA 负环
记录最短路径长度,若大于等于 \(n\),则存在负环。
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef long long ll;
const ll N=2e3,M=3e3,MAX=1ll<<63-1;
int T,n,m,u,v,w,top,h[N+1];
struct edge{
int v,r;
ll w;
}a[2*M+1];
void create(int u,int v,ll w){
a[++top]={v,h[u],w};
h[u]=top;
}
bool SPFA(int s){
static int pl,c[N+1];
static ll dis[N+1];
static bool flag[N+1];
fill(dis+1,dis+n+1,MAX);
dis[s]=0;
fill(c+1,c+n+1,0);
fill(flag+1,flag+n+1,false);
queue<int>q;
q.push(s);
flag[s]=true;
while(q.size()){
pl=q.front();
q.pop();
flag[pl]=false;
for(int i=h[pl];i>0;i=a[i].r){
if(dis[pl]+a[i].w<dis[a[i].v]){
dis[a[i].v]=dis[pl]+a[i].w;
c[a[i].v]=c[pl]+1;
if(c[pl]>=n)return true;
if(flag[a[i].v]==false)q.push(a[i].v);
}
}
}return false;
}
void Start(){
top=0;
memset(h,0,sizeof(h));
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
scanf("%d",&T);
while(T--){
Start();
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d %d %d",&u,&v,&w);
create(u,v,w);
if(w>=0)create(v,u,w);
}
printf("%s\n",(SPFA(1)?"YES":"NO"));
}
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
时间复杂度均为 \(\mathcal O(nm)\)。
笑话。

浙公网安备 33010602011771号