【模板】差分约束算法
简单来说,这个 $x_i-x_j\le k$ 的形式可以化成 $x_i\le x_j+k$ 这样的类似于松弛的形式。
于是可以建一条 $j\rightarrow i$ 权值为 $k$ 的有向边来表示这种关系。
最后是否有解就是在询问整个差分约束系统是否有负环。
求解的话,很显然如果说 ${a_1,\cdots ,a_n}$ 是一组解,那么必然有 ${a_1+\Delta,\cdots ,a_n+\Delta}$ 也是一组解。
所以我们干脆求出非正数解。
那么就有这样一组差分约束:$x_i-x_{n+1}\le 0$,其中 $x_{n+1}=0$。
就是建 $n$ 条从 $n+1$ 指向各个点的有向边,边权为 0,并且 $dis_{n+1}=0$ 就可以了。
时间复杂度 $O(nm)$。
注意在增加源点 $n+1$ 之后我们的点数变成了 $n+1$,判断负环的时候不要写错。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<vector> #include<cstring> #define ll long long using namespace std;
const ll N=5e4,M=5e4;
ll n,m,u,v,w,tot,flg,h;
ll ver[M+5],nxt[M+5],head[N+5],wt[M+5];
ll inq[N+5],cnt[N+5],f[N+5];
bool vis[N+5];
queue<ll> q;
void spfa() { memset(vis,0,sizeof(vis)); memset(f,0x3f,sizeof(f)); f[n+1]=0;q.push(n+1); while(!q.empty()) { h=q.front();q.pop();vis[h]=0; for(ll i=head[h];i;i=nxt[i]) { if(f[ver[i]]>f[h]+wt[i]) { f[ver[i]]=f[h]+wt[i];cnt[ver[i]]=cnt[h]+1; if(cnt[ver[i]]>=n+1) {flg=1;return;} if(!vis[ver[i]]) { q.push(ver[i]);vis[ver[i]]=1; inq[ver[i]]++; if(inq[ver[i]]>=n+1) {flg=1;return;} } } } } }
void add(ll u,ll v,ll w) { ver[++tot]=v;wt[tot]=w; nxt[tot]=head[u];head[u]=tot; }
inline ll read() { ll ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-f;ch=getchar();} while(ch>='0'&&ch<='9') {ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();} return ret*f; }
void write(ll x) { static char buf[22];static ll len=-1; if(x>=0) { do{buf[++len]=x%10+48;x/=10;}while(x); } else { putchar('-'); do{buf[++len]=-(x%10)+48;x/=10;}while(x); } while(len>=0) putchar(buf[len--]); }
int main() {
n=read();m=read();
for(ll i=1;i<=m;i++) { u=read();v=read();w=read(); add(v,u,w); }
for(ll i=1;i<=n;i++) { add(n+1,i,0); }
spfa();
if(flg) printf("NO"); else { for(ll i=1;i<=n;i++) { write(f[i]);putchar(' '); } }
return 0; }
|