1. 程式人生 > >2018.09.28【Vijos1053】Easy sssp(SPFA判負環)

2018.09.28【Vijos1053】Easy sssp(SPFA判負環)

傳送門

解析:

深入理解SPFASPFA的本質。

思路:

由於是佇列優化的BellmanFordBellman-FordSPFASPFA也具有判負環的功能,但不同的是BellmanFordBellman-Ford可以直接求出負環大小。

一般來說,求最短路我們會用BFSBFS版的SPFASPFA,而判負環我們選擇DFSDFS版的SPFASPFA

具體實現請看程式碼。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register #define gc getchar #define pc putchar #define cs const inline int getint(){ re int num; re char c; re bool f=0; while(!isdigit(c=gc()))f^=c=='-';num=c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return f?-num:num; } inline void outint(ll a){ static
char ch[23]; if(a==0)pc('0'); if(a<0)pc('-'),a=-a; while(a)ch[++ch[0]]=a-a/10*10,a/=10; while(ch[0])pc(ch[ch[0]--]^48); } cs int N=1002; cs int M=100005; int n,m,s; int last[N],nxt[M],to[M],ecnt; ll w[M]; inline void addedge(int u,int v,ll val){ nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val; } bitset<
N> vis,inq,cal; ll dist[N]; inline bool SPFA(int u){ cal[u]=inq[u]=true; for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){ if(dist[v]>dist[u]+w[e]){ dist[v]=dist[u]+w[e]; if(inq[v]||!SPFA(v))return inq[u]=false; } } inq[u]=false; return true; } queue<int> q; inline void spfa(int s){ inq.reset(); vis.reset(); memset(dist,0x3f,sizeof dist); q.push(s);dist[s]=0; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=true; inq[u]=false; for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){ if(dist[v]>dist[u]+w[e]){ dist[v]=dist[u]+w[e]; if(!inq[v])q.push(v),inq[v]=1; } } } } signed main(){ n=getint(); m=getint(); s=getint(); for(int re i=1;i<=m;++i){ int u=getint(),v=getint(),val=getint(); if(u==v&&val<0){puts("-1");return 0;} addedge(u,v,val); } inq.reset(); vis.reset(); cal.reset(); for(int re i=1;i<=n;++i){ if(!cal[i]) if(!SPFA(i)){puts("-1");return 0;} } spfa(s); for(int re i=1;i<=n;++i){ if(!vis[i])puts("NoPath"); else outint(dist[i]),pc('\n'); } return 0; }