查分约束可用一般可用来求:
1.不等式组的的可行解
2.如何求最大值或最小值
求解一般步骤:
1图中的限制转换为不等式(xi<=xj+c)的形式,转换为xj到xi的长度为c的边。、
【求最小值时应求最长路,则应为xi>=sj+c的形式】。
2.找一个超级原点,使原点可遍历所有边(或点)。【看题目是要求边还是点】。
3.从原点开始遍历。
例题
本题为纯差分约束,且要求最小值,即应求长最路。(xi>=xj+c)
建图分为五种情况:
1.第 A个小朋友分到的糖果必须和第 B个小朋友分到的糖果一样多 -> A>=B&&a<=B -> add(B,A,0),add(A,B,0)
2.第 A个小朋友分到的糖果必须少于第 B 个小朋友分到的糖果 -> A<B -> add(A,B,1)
3.A个小朋友分到的糖果必须不少于第 B个小朋友分到的糖果 -> A>=B -> add(B,A,0)
4. A个小朋友分到的糖果必须多于第 B个小朋友分到的糖果 -> A>B -> add(B,A,1)
5.A个小朋友分到的糖果必须不多于第 B个小朋友分到的糖果 -> A<=B -> add(A,B,0)
接下来spfa求最长路。dis[i]表示第i个人分到的最小值。
【queue会超时,应用栈优化】(还没学会手写队列,今晚学下,明天优化)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=500000,M=2*N;
int n,k;
int dis[N],cnt[N];
int h[N],e[M],w[M],ne[M],idex;
bool st[M];
void add(int a,int b,int c)
{
w[idex]=c,e[idex]=b,ne[idex]=h[a],h[a]=idex++;
}
bool spfa()
{
memset(cnt,0,sizeof cnt);
memset(dis,-0x3f,sizeof dis);
queue<int>q;
q.push(0);
st[0]=1;
dis[0]=0;
while(q.size())
{
int t=q.front();
st[t]=0;
q.pop();
for(int i=h[t];~i;i=ne[i])
{
int j=e[i];
if(dis[j]<dis[t]+w[i])
{
dis[j]=dis[t]+w[i];
cnt[j]=cnt[t]+1;
if(cnt[j]>=n+1)return false;
if(!st[j])
{
st[j]=1;
q.push(j);
}
}
}
}
return true;
}
int main()
{
cin>>n>>k;
memset(h,-1,sizeof h);
while(k--)
{
int x,a,b;
cin>>x>>a>>b;
if(x==1)add(a,b,0),add(b,a,0);
else if(x==2)add(a,b,1);
else if(x==3)add(b,a,0);
else if(x==4)add(b,a,1);
else if(x==5)add(a,b,0);
}
if(!spfa())cout <<-1;
else
{
int max_;
for(int i=1;i<=n;i++)
{
max_+=dis[i];
}
cout<<max_;
}
return 0;
}
s[i]为前i个有多少和数字
建图分为三种情况
1. Sb-Sa>=c
2. si-s(i-1)<=1(每个数字只能存下一个)
3. si>=s(i-1)(前缀和后必大于或等于前)
最终只需求出dis[50001]的大小即可
(应寻找建图的条件,应从题意和各种自身限制寻找)
x[i]表示第i头牛所处于的位置。
建图可以分为三种情况
1.1 每头奶牛按编号排序 i+1 → i w = 0
<=> x[i] ≤ x[i+1]
2 两者之间的距离不超过一个给定的数L
x[b]-x[a] ≤ L a → b w = L
x[b] ≤ x[a] + L
3 两者之间的距离不小于一个给定的数D
x[b]-x[a] ≥ D
x[a] ≤ x[b]-D b → a w = -D
本题有三个问
1.判断负环可以建立超级原点,遍历判断
2.将x[1]固定为0.从1开始进行spfa.
3.dis[n]为最终结果。
本题为暴力搜索+差分约束
从0开始搜索固定s24的大小,若存在正环,则就是答案。
建图分为:
. x[i] 表示当前时段的人数,s[i] 表示 x[1~i] 的总人数,num[i] 表示当前时段来的人数
1. 0 <= s[i] - s[i-1] <= num[i]:s[i] >= s[i-1] + 0;s[i-1] >= s[i] - num[i]
2. 8 <= i <= 24:s[i] >= s[i-8] + r[i]
3. 1 <= i <= 7:s[i] >= s[i+16] + r[i] - s[24]