特殊的SPFA判斷負環

別人的介紹 

借用了大佬的思考:

賦所有dis[i]=0,跑最長路,如果某個元素入隊次數超過點數就說明有正環。

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

論文裏高大上看不懂,蒟蒻用簡單粗暴的方法想了一下:

如果某個環有K個點組成,BFS會從K個點中的某個點開始,每次都換一個點擴展一次,可能達到O(N*K^2)

DFS則只選其中的一個點不斷擴展,K次就能使自己重新入隊一次,這樣就是O(N*K)

孰優孰劣一眼分明

#include<bits/stdc++.h>
#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 <typename _Tp> 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<node> 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<int> 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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章