农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N。
于是约翰拍摄了M(1 <= M <= 100,000)张照片,每张照片都覆盖了连续一段奶牛:第i张照片中包含了编号a_i 到 b_i的奶牛。但是这些照片不一定把每一只奶牛都拍了进去。
在拍完照片后,约翰发现了一个有趣的事情:每张照片中都有且仅有一只身上带有斑点的奶牛。约翰意识到他的牛群中有一些斑点奶牛,但他从来没有统计过它们的数量。 根据照片,请你帮约翰估算在他的牛群中最多可能有多少只斑点奶牛。如果无解,输出“-1”。
很容易想到差分约束 而且边也很好建 唯一要考虑的是spfa 果然又被卡了
采用双端队列优化 且遍历了一定的值以后直接退出即可
![P3084 [USACO13OPEN]照片Photo 差分约束_最长路](https://s2.51cto.com/images/blog/202108/07/e079f2ad4c01fb9ea6ca443d2a4ecf7c.gif)
![P3084 [USACO13OPEN]照片Photo 差分约束_i++_02](https://s2.51cto.com/images/blog/202108/07/e681c57fedae35edeaae93388b971b84.gif)
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3
const int N=200000+5;
const int M=10*N;
int n,k;
int pos,head[M],tot;
struct Edge
{
int nex,to,v;
}edge[M];
void add(int a,int b,int c)
{
edge[++pos].nex=head[a];
head[a]=pos;
edge[pos].to=b;
edge[pos].v=c;
}
int dis[N];
int vis[N];
int cnt[N];
int spfa()
{
deque<int>q;
rep(i,1,n)dis[i]=inf;
dis[0]=0;
vis[0]=1;
q.push_back(0);
while(!q.empty())
{
int x=q.front();
q.pop_front();
vis[x]=0;
for(int i=head[x];i;i=edge[i].nex)
{
int v=edge[i].to,w=edge[i].v;
if(dis[v]>dis[x]+w)
{
dis[v]=dis[x]+w;
if(!vis[v])
{
if(++tot>800000)return 0;
vis[v]=1;
if(q.size()&&dis[v]>dis[q.front()])q.push_back(v);
else q.push_front(v);
}
}
}
}
return dis[n];
}
int main()
{
cin>>n>>k;
rep(i,1,k)
{
int a,b;cin>>a>>b;
add(a-1,b,1);add(b,a-1,-1);
}
rep(i,1,n)add(i-1,i,1),add(i,i-1,0);
if(spfa())
cout<<dis[n];
else cout<<"-1";
return 0;
}
一般这种求最多的 要用最短路 (也就是 <= 式子 )
求最少的 用最长路
















