spfa判负环

时间:2023-03-10 02:31:57
spfa判负环

bfs版spfa

void spfa(){
queue<int> q;
for(int i=;i<=n;i++) dis[i]=inf;
q.push();dis[]=;vis[]=;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]){
vis[v]=;q.push(v);
}
}
}
}
}

dfs无优化版spfa

void spfa(int u){
instack[u]=;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!instack[v])
spfa(v);
else return;
}
}
instack[u]=;
}

dfs版spfa判断环

bool spfa(int u){
vis[u]=;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(vis[v]||!spfa(v))
return ;}
}vis[u]=;return ;
}

spfa判负环:luogu 3385

p.s:其实此题也是要先判连通性的,数据水过

1.bfs无优化版  O(n*m)    40

#include<bits/stdc++.h>

using namespace std;

const int inf=0x3f3f3f3f;
const int N=;
const int M=; int n,m,u,v,w,t;
int cnt[N],vis[N],head[N],dis[N],tot;
struct node{int v,w,next;}e[M];
void insert(int u,int v,int w){
e[++tot]=(node){v,w,head[u]};head[u]=tot;} int spfa(){
queue<int> q;
memset(dis,inf,sizeof(dis));
memset(vis,,sizeof(vis));
memset(cnt,,sizeof(cnt));
dis[]=;vis[]=;q.push();
while(!q.empty()){
int u=q.front();q.pop();cnt[u]++; if(cnt[u]>n) return ;
if(dis[u]==inf) continue;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
vis[v]=;
q.push(v);
}
}vis[u]=;
}
return ;
}
int main(){
cin>>t;
while(t--){
memset(head,,sizeof head);
memset(e,,sizeof e);
tot=;
cin>>n>>m;
for(int i=;i<=m;i++){
cin>>u>>v>>w;
insert(u,v,w);
if(w>=) insert(v,u,w);}
if(spfa()) printf("YE5\n");
else printf("N0\n");
}
return ;
}

2.bfs优化版(虽然思路清奇但是能AC就行)

更新p.s: 1.没有判连通性 2.无法处理有负边无负环的情况,cnt[v]=cnt[u]+1,并不通用

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define dec(i,x,y) for(register int i=x;i>=y;i--)
#define ll long long
using namespace std; const int N=20005;
const int M=100010;
const int inf=0x3f3f3f3f; inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}int n,m; int vis[N],dis[N],cnt[N],s=1; int head[N],tot;
struct node{int v,w,next;}e[M];
void insert(int u,int v,int w){
e[++tot]=(node){v,w,head[u]};head[u]=tot;} inline int spfa(){
queue<int> q;
memset(dis,inf,sizeof dis);
memset(vis,0,sizeof vis);
memset(cnt,0,sizeof cnt);
dis[s]=0;vis[s]=1;cnt[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(!vis[v]){
cnt[v]=cnt[u]+1;
if(cnt[v]>=n) return 1;
vis[v]=1,q.push(v);
}
}
}
}return 0;
} int main(){
int t=read();
while(t--){
n=read();m=read();
memset(head,0,sizeof head);
tot=0;
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
insert(u,v,w);
if(w>=0) insert(v,u,w);
}if(spfa()) printf("YE5\n");
else printf("N0\n");
}return 0;
}

3.dfs版,dis置0   0

#include<bits/stdc++.h>

using namespace std;

const int N=;
int t,n,m,cnt,dis[N],vis[N],head[N],fg;
struct node{int v,w,next;}e[N<<]; inline void insert(int u,int v,int w){
e[++cnt]=(node){v,w,head[u]};head[u]=cnt;} void spfa(int u){
vis[u]=;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(dis[v]>dis[u]+w){
if(vis[v]||fg){fg=;break;}
dis[v]=dis[u]+w;
spfa(v);
}
}vis[u]=;
}int a,b,w;
int main(){
cin>>t;
while(t--){
memset(dis,,sizeof dis);//dis置0
memset(vis,,sizeof vis);
memset(head,,sizeof head);
memset(e,,sizeof e);
cnt=;
cin>>n>>m;
for(int i=;i<=m;i++){
cin>>a>>b>>w;
insert(a,b,w);
if(w>=) insert(b,a,w);
}fg=;
for(int i=;i<=n;i++){
spfa(i);if(fg)break;}
if(fg) printf("YE5");
else printf("N0");
}return ;
}

4.dfs简单版

#include<bits/stdc++.h>
#define il inline
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
const int N=,inf=;
int n,m,to[N],net[N],w[N],dis[N],cnt,h[N],tot[N];
bool vis[N]; il int gi(){
int a=;char x=getchar();
while(x<''||x>'')x=getchar();
while(x>=''&&x<='')a=(a<<)+(a<<)+x-,x=getchar();
return a;
} il void add(int u,int v,int c){to[++cnt]=v,net[cnt]=h[u],h[u]=cnt,w[cnt]=c;} il bool spfa(int u){
vis[u]=;
for(int i=h[u];i;i=net[i])
if(dis[to[i]]<dis[u]+w[i]){
dis[to[i]]=dis[u]+w[i];
if(vis[to[i]])return ;
if(!spfa(to[i]))return ;
}
vis[u]=;
return ;
} int main(){
n=gi(),m=gi();
int f,a,b,c;
while(m--){
f=gi(),a=gi(),b=gi();
if(f==)c=gi(),add(b,a,c);
else if(f==)c=gi(),add(a,b,-c);
else if(f==)add(a,b,),add(b,a,);
}
For(i,,n)add(,i,),dis[i]=-inf;
if(!spfa())cout<<"No";
else cout<<"Yes";
return ;
}