1. 程式人生 > 實用技巧 >負環操作 的佇列

負環操作 的佇列

說明

(今天又用雙端佇列寫了一個別的spfa題,也有負環操作,是可以過的,所以就是說用雙端佇列其實跟佇列是一樣的,都能判出負環,我覺得可能不用太在意什麼隊列了吧,但是這道洛谷題用雙端佇列會出問題,所以要用queue,可能是題目的原因)
--2020.7.16修改
(我發現,用雙端佇列常數較大,所以在做某些差分約束題的時候,若判斷能否成立(負環),最好用queue,deque的常數可能會超時例如·洛谷·「P1993小K的農場」)
--2020.7.19修改

「模板」負環

  • 不要deque,否則會出錯(不知道什麼原因),就是可能會多判負環
  • 用queue是正常的
  • 自己的出錯資料
  • 正確答案為:NO(應該是無負環)

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int maxn=2e3+5,maxm=6e3+5;
int n,m,head[maxn],dis[maxn],cnt[maxn],cc;
struct Edge{int to,next,val;}e[maxm];
bool vis[maxn];
void A(int x,int y,int z){
	e[++cc].to=y;
	e[cc].next=head[x];
	e[cc].val=z;
	head[x]=cc;
}
void Init(){
	cc=0;
	memset(head,0,sizeof head);
	memset(e,0,sizeof e);
	memset(cnt,0,sizeof cnt);
	memset(vis,0,sizeof vis);
}
bool spfa(int s){
	for(int i=1;i<=n;++i)dis[i]=0x3f3f3f3f;
	queue<int>q;
	dis[s]=0;vis[s]=1;q.push(s);
	while(!q.empty()){
		int x=q.front();q.pop();vis[x]=0;
		for(int i=head[x];i;i=e[i].next){
			int y=e[i].to;
			if(dis[y]>dis[x]+e[i].val){
				dis[y]=dis[x]+e[i].val;
				if(!vis[y]){
					if(++cnt[y]>n){
						return 1;
					}
					vis[y]=1;
					q.push(y);
				}
			}
		}
	}
	return 0;
}
int main(){
//	freopen("1.in","r",stdin);
	int t;scanf("%d",&t);
	while(t--){
		Init();
		scanf("%d%d",&n,&m);
		for(int i=1,x,y,z;i<=m;++i){
			scanf("%d%d%d",&x,&y,&z);
			if(z>=0)A(x,y,z),A(y,x,z);
			else A(x,y,z);
		}
		if(spfa(1))printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

正確答案:

NO

我用deque卻跑出來是yes......
資料