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;
}
posted @ 2019-10-09 17:32  ChrisKKK  阅读(96)  评论(0编辑  收藏  举报