1. 程式人生 > 實用技巧 >洛谷 P3385 【模板】負環 (SPFA)

洛谷 P3385 【模板】負環 (SPFA)

  • 題意:有一個\(n\)個點的有向圖,從\(1\)出發,問是否有負環.

  • 題解:我們可以用SPFA來進行判斷,在更新邊的時候,同時更新路徑的邊數,因為假如有負環的話,SPFA這個過程一定會無限重複的遍歷這個環,那麼這個環中的邊數也就會不斷增加,因為我們只有\(n\)個點,所以假如某條路徑的邊數\(\ge n\)時,就說明有點重複使用了,也就說明一定存在負環.這題讓我們從1開始走,所以只要對1初始化一下就行了.

  • 程式碼:

    struct misaka{
    	int out;
    	int val;
    }e;
    
    int t;
    int n,m;
    int dis[N];
    bool st[N];
    int cnt[N];
    vector<misaka> v[N];
    
    bool spfa(){
    
    	queue<int> q;
    
    	st[1]=true;
    	dis[1]=0;
    	q.push(1);
    
    	while(!q.empty()){
    		int node=q.front();
    		q.pop();
    
    		st[node]=false;
    
    		for(auto w:v[node]){
    			int now=w.out;
    			if(dis[now]>dis[node]+w.val){
    				dis[now]=dis[node]+w.val;
    				cnt[now]=cnt[node]+1;
    				if(cnt[now]>=n) return true;
    				if(!st[now]){
    					st[now]=true;
    					q.push(now);
    				}
    			}
    		}
    	}
    	return false;
    }
    
    int main() {
        //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d %d",&n,&m);
    		for(int i=1;i<=n;++i){
    			dis[i]=INF;
    			st[i]=false;
    			cnt[i]=0;
    		}
    		for(int i=1;i<=m;++i){
    			int a,b,val;
    			scanf("%d %d %d",&a,&b,&val);
    			if(val>=0){
    				v[a].pb({b,val});
    				v[b].pb({a,val});
    			}
    			else
    			v[a].pb({b,val});
    		}
    
    		if(spfa()) puts("YES");
    		else puts("NO");
    		for(int i=1;i<=n;++i){
    			v[i].clear();
    		}
    	}
    
        return 0;
    }