判负环

众所周知,SPFA可以判负环。如果采用BFS,那么存在负环的充要条件就是一个点入队超过总点数次。但不难看出,这样的方法效率是很低的。

我们考虑DFS。

如果题目只要求判断负环,我们便有一种效率稍高的方法:将dis数组初始化为0,对每个点跑一遍dfs即可,如果能在一次搜索中搜到重复的点,那么负环就存在。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 2000000+10 
typedef long long LL;
struct ed{int v,next;LL w;}edge[MAXN*2];
int n,m,tot,head[MAXN],vis[MAXN];
bool flag=false;
LL dis[MAXN];
void add(int u,int v,LL w){
    edge[++tot].v=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot;
}
void dfs(int u){
    if(flag)return;
    vis[u]=1;
    for(int i=head[u];i;i=edge[i].next){
        int v=edge[i].v;
        if(flag)return;
        if(dis[u]+edge[i].w<dis[v]){
            dis[v]=dis[u]+edge[i].w;
            if(vis[v]){
                flag=true;
                return;
            }
            else dfs(v);
        }
    }
    vis[u]=0;
}
void init(){
    tot=0;
    memset(head,0,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));    
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        init();    
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v;LL w;
            scanf("%d%d%lld",&u,&v,&w);
            add(u,v,w);
            if(w>0)add(v,u,w);
        }
        flag=false;
        for(int i=1;i<=n;i++){
            dfs(i);
            if(flag)break;
        }
        puts(flag?"YES":"NO");
    }
    return 0;
}

 

posted @ 2017-11-03 08:36  NINGLONG  阅读(186)  评论(0编辑  收藏  举报