vue從入門到精通指南
阿新 • • 發佈:2020-11-28
雖然SPFA已死,但是SPFA還是很有用處的
具體實現與dijkstra 相似,但是是利用佇列優化,在廣度上進行求解(可處理負邊權),在每次鬆弛時,保證所有深度為n的路徑最短
應用
1.存在負邊權
2.每個點可以被多次經過
3.判斷負(正)環
code
#include<iostream> #include<cstdio> #include<math.h> #include<cstring> #include<vector> #include<queue> #include<algorithm> #define ll long long const ll maxn=3e3+10; ll t,n,m,tot; ll dis[maxn],vis[maxn],ru[maxn],head[maxn]; std::vector<std::pair<ll,ll> > e[maxn]; inline void cl() { tot=0; memset(head,0,sizeof(head)); for(int i=1;i<=n;i++) e[i].clear(); } inline bool spfa(ll x) { for(int i=1;i<=maxn;i++) dis[i]=0x7fffffff,vis[i]=0,ru[i]=0; std::queue<ll> q; dis[x]=0; vis[x]=1; q.push(x); while(q.size()) { ll u=q.front(); q.pop(); vis[u]=0; for(int i=0;i<e[u].size();i++) { ll v=e[u][i].first; ll w=e[u][i].second; if(dis[v]>dis[u]+w) { dis[v]=dis[u]+w; if(!vis[v]) { q.push(v); vis[v]=1; ru[v]++; if(ru[v]>=n)//當存在負環時,會不斷經過環上的路徑更新最小值,當一條路徑被走過了 n 次以上,那麼圖中必然存在負環 { return 1; } } } } } return 0; } int main(void) { scanf("%lld",&t); while(t--) { cl(); scanf("%lld %lld",&n,&m); for(int i=1;i<=m;i++) { ll x,y,z; scanf("%lld %lld %lld",&x,&y,&z); if(z>=0) e[y].push_back(std::make_pair(x,z)); e[x].push_back(std::make_pair(y,z)); } ll flag=spfa(1); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }