負環操作 的佇列
阿新 • • 發佈:2020-07-19
說明
(今天又用雙端佇列寫了一個別的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......
資料