特殊的SPFA判断负环

别人的介绍 

借用了大佬的思考:

赋所有dis[i]=0,跑最长路,如果某个元素入队次数超过点数就说明有正环。

使用DFS版本的SPFA做比BFS快10倍,为什么?

论文里高大上看不懂,蒟蒻用简单粗暴的方法想了一下:

如果某个环有K个点组成,BFS会从K个点中的某个点开始,每次都换一个点扩展一次,可能达到O(N*K^2)

DFS则只选其中的一个点不断扩展,K次就能使自己重新入队一次,这样就是O(N*K)

孰优孰劣一眼分明

#include
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=3e5+5;
template  il void read(_Tp&x) {
	char ch;bool flag=0;x=0;
	while(ch=getchar(),!isdigit(ch)) if(ch=='-')flag=1;
	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	if(flag) x=-x;
}
//il int Add(int &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(int &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
int T,n,M1,M2;
struct node{int to,w;};
vector G[N];

il void init(){
    for(int i=0;i<=n;++i) G[i].clear();
}
il void add(int u,int v,int w){
    G[u].push_back({v,w});
}
int ins[N],dis[N],t[N];
il bool ck(){ //判断负环 
    for(int i=0;i<=n;++i) ins[i]=dis[i]=t[i]=0;
    stack stk;
    for(int i=0;i<=n;++i){
        ins[i]=1,t[i]=1;
        stk.push(i);
    }
    int u;
    while(!stk.empty()){
        u=stk.top(),stk.pop();
        ins[u]=0;
        for(auto tp:G[u]){
            int to=tp.to,w=tp.w;
            if(dis[to]>dis[u]+w){
                dis[to]=dis[u]+w;
                if(!ins[to]){
                    stk.push(to);
                    ins[to]=1,t[to]++;
                    if(t[to]==n+2) return false; //有负环 
                }
            }
        }
    }
    return true;//无负环 
}
int main(){
//    std::ios::sync_with_stdio(0);cin.tie(0);

    return 0;
}

 

你可能感兴趣的:(算法总结)