spfa判负环

bfs版spfa

void spfa(){
    queue<int> q;
    for(int i=1;i<=n;i++) dis[i]=inf;
    q.push(1);dis[1]=0;vis[1]=1;
    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]=1;q.push(v);
                }
            }
        }
    }
}

dfs无优化版spfa

void spfa(int u){
    instack[u]=1;
    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]=0;
}

dfs版spfa判断环

bool spfa(int u){
    vis[u]=1;
    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 0;}
    }vis[u]=0;return 1;
}

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=2005;
const int M=3005;

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,0,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    dis[1]=0;vis[0]=1;q.push(1);
    while(!q.empty()){
        int u=q.front();q.pop();cnt[u]++;
        
        if(cnt[u]>n) return 1;
        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]=1;
                q.push(v);
            }
        }vis[u]=0;
    }
    return 0;
}
int main(){
    cin>>t;
    while(t--){
        memset(head,0,sizeof head);
        memset(e,0,sizeof e);
        tot=0; 
        cin>>n>>m;
        for(int i=1;i<=m;i++){
           cin>>u>>v>>w;
           insert(u,v,w);
        if(w>=0) insert(v,u,w);}
        if(spfa()) printf("YE5\n");
        else printf("N0\n");
    }
    return 0;
}

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=210005; 
int t,n,m,cnt,dis[N],vis[N],head[N],fg;
struct node{int v,w,next;}e[N<<1];

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]=1;
    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=1;break;}
            dis[v]=dis[u]+w;
            spfa(v);
        }
    }vis[u]=0;
}int a,b,w;
int main(){
    cin>>t;
    while(t--){
        memset(dis,0,sizeof dis);//dis置0
        memset(vis,0,sizeof vis);
        memset(head,0,sizeof head);
        memset(e,0,sizeof e);
        cnt=0;
        cin>>n>>m;
        for(int i=1;i<=m;i++){
           cin>>a>>b>>w;
           insert(a,b,w);
           if(w>=0) insert(b,a,w);
        }fg=0;
        for(int i=1;i<=n;i++){
            spfa(i);if(fg)break;}
        if(fg) printf("YE5");
        else printf("N0");
    }return 0;
}

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=50005,inf=23333333;
int n,m,to[N],net[N],w[N],dis[N],cnt,h[N],tot[N];
bool vis[N];

il int gi(){
    int a=0;char x=getchar();
    while(x<'0'||x>'9')x=getchar();
    while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,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]=1;
    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 0;
            if(!spfa(to[i]))return 0;
        }
    vis[u]=0;
    return 1;
}

int main(){
    n=gi(),m=gi();
    int f,a,b,c;
    while(m--){
        f=gi(),a=gi(),b=gi();
        if(f==1)c=gi(),add(b,a,c);
        else if(f==2)c=gi(),add(a,b,-c);
        else if(f==3)add(a,b,0),add(b,a,0);
    }
    For(i,1,n)add(0,i,0),dis[i]=-inf;
    if(!spfa(0))cout<<"No";
    else cout<<"Yes";
    return 0;
}

 

posted @ 2018-08-27 20:54  ASDIC减除  阅读(166)  评论(0编辑  收藏  举报