农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N。
于是约翰拍摄了M(1 <= M <= 100,000)张照片,每张照片都覆盖了连续一段奶牛:第i张照片中包含了编号a_i 到 b_i的奶牛。但是这些照片不一定把每一只奶牛都拍了进去。
在拍完照片后,约翰发现了一个有趣的事情:每张照片中都有且仅有一只身上带有斑点的奶牛。约翰意识到他的牛群中有一些斑点奶牛,但他从来没有统计过它们的数量。 根据照片,请你帮约翰估算在他的牛群中最多可能有多少只斑点奶牛。如果无解,输出“-1”。
很容易想到差分约束 而且边也很好建 唯一要考虑的是spfa 果然又被卡了
采用双端队列优化 且遍历了一定的值以后直接退出即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.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; }
一般这种求最多的 要用最短路 (也就是 <= 式子 )
求最少的 用最长路