1. 程式人生 > >差分約束——洛谷 P1645 序列

差分約束——洛谷 P1645 序列

https://www.luogu.org/problem/show?pid=1645
基本上就是差分約束spfa的模版題;
我們搞一個a[]
如果序列裡有i那麼a[i]=1;
s[i]就是a[i]的字首和;
那麼
s[i]-s[i-1]>=0
s[i-1]-s[i]>=-1
對於讀入的x,y,z;
s[y]-s[x-1]>=z
所以我們把i到i-1連-1的邊
i-1到i連0的邊
x-1到y連z的邊
在跑一邊spfa求0-max(y)的最長路就好了;
至於原因,大家可以模擬一下,很顯然的一個構造
我不會證明

#include<bits/stdc++.h>
#define Ll unsigned long long using namespace std; const int N=100050; struct cs{int to,nxt,v;}a[N*2]; int head[N],ll,d[N]; bool in[N]; int n,m,x,y,z; void init(int x,int y,int z){ a[++ll].to=y; a[ll].v=z; a[ll].nxt=head[x]; head[x]=ll; } void spfa(int S,int E){ queue<int>Q; memset
(d,-63,sizeof d); d[S]=0;Q.push(S); while(!Q.empty()){ int x=Q.front();Q.pop();in[x]=0; for(int k=head[x];k;k=a[k].nxt) if(d[a[k].to]<d[x]+a[k].v){ d[a[k].to]=d[x]+a[k].v; if(!in[a[k].to])in[a[k].to]=1,Q.push(a[k].to); } } printf
("%d",d[n]); } int main() { scanf("%d",&m); while(m--){ scanf("%d%d%d",&x,&y,&z); init(x-1,y,z); n=max(y,n); } for(int i=1;i<=n;i++){ init(i-1,i,0); init(i,i-1,-1); } spfa(0,n); }