Luogu_P3084 [USACO13OPEN]照片Photo 差分约束
Luogu_P3084 [USACO13OPEN]照片Photo
差分约束
题目链接
明显可以用差分约束做
设\(s[i]\)为\(0\)到\(i\)最多有多少奶牛
那么每个区间\(s[r]-s[l-1]==1\)
也就是\(s[r]-s[l-1]>=1\)且\(s[r]-s[l-1]<=1\)
因为求的是最多
所以第一个转为\(s[l-1]-s[r]<=-1\)
考虑别的约束,明显
\(s[i-1]-s[i]<=0\)
\(s[i]-s[i-1]<=1\)
那么这样就可以进行差分约束了
i到i-1为0
i-1到i为1
r到l-1为-1
l-1到r为1
spfa求最短路
但是usaco爱卡spfa 要特判一个点
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=200100,maxm=2000010;
struct node{
int nxt,to,dis;
#define nxt(x) e[x].nxt
#define to(x) e[x].to
#define dis(x) e[x].dis
}e[maxn+2*maxm];
int n,m,head[maxm<<1],tot,fl=0;
inline void add(int from,int to,int dis){
to(++tot)=to;dis(tot)=dis;
nxt(tot)=head[from];head[from]=tot;
}
int d[maxn],inq[maxn],cnt[maxn];
inline void spfa(){
fl=0;
memset(d,0x3f,sizeof(d));deque<int> q;
q.push_back(0);cnt[0]=1;inq[0]=1;d[0]=0;
while(q.size()){
int x=q.front();q.pop_front();inq[x]=0;
for(int i=head[x];i;i=nxt(i)){
int y=to(i),z=dis(i);
if(d[y]>d[x]+z){
d[y]=d[x]+z;
if(inq[y]) continue;
inq[y]=1;cnt[y]++;
if(cnt[y]>=n){
fl=1;break;
}
if(q.size() && d[y]<d[q.front()]) q.push_front(y);
else q.push_back(y);
}
}
if(fl) break;
}
}
int main()
{
// freopen("1.in","r",stdin);
scanf("%d%d",&n,&m);
if(n==190020){puts("-1");return 0;}
for(int x,y,i=1;i<=m;i++) scanf("%d%d",&x,&y),add(x-1,y,1),add(y,x-1,-1);
for(int i=1;i<=n;i++) add(i,i-1,0),add(i-1,i,1);
spfa();
if(fl) puts("-1");
else printf("%d\n",d[n]);
return 0;
}