差分约束
差分约束总的有两种
因为有判环和负数,所以一般用SPFA
- 题目求最小值,则就是差的最大值,跑最长路,转换为\(s_i>=s_j+w\)即\(add(s_j,s_i,w)\)
- 题目求最大值,则就是差的最小值,跑最短路,转换为\(s_i<=s_j+w\)即\(add(s_j,s_i,w)\)
有时不等式变号出现负数
判断负环时,需建超级远点0或n+1
Layout 排队布局
需建超级原点判负环,还要算出距离
注意,差分约束为有向图,所以图可能不连通,所以我们要找到题目中的隐含条件
如本题,能看出隐含条件\(s_{i+1}-s_i>=0\)这样图就连通了!!
后一个,一定大于等于前一个
顾
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
int n,m,d,cnt,head[N],dis[N],tot[N];bool vis[N];
struct EDGE
{
int u,to,next,w;
}edge[N*2];
void add(int u,int v,int w)
{
edge[++cnt].u=u;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
}
int spfa(int st)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(st);
dis[st]=0;vis[st]=1;
tot[st]++;
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=edge[i].next)
{
int to=edge[i].to;int w=edge[i].w;
// cout<<dis[to]<<endl;
if(dis[to]>dis[u]+w)
{
dis[to]=dis[u]+w;
if(!vis[to])
{
tot[to]++;
q.push(to);
if(tot[to]>n)
{
cout<<-1<<endl;
exit(0);
}
}
}
}
}
if(dis[n]<0)return 1;
return 3;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>d;
for(int i=1;i<=n;i++)add(0,i,0);
for(int i=1;i<n;i++)
{
add(i+1,i,0);
}
int a,b,w;
for(int i=1;i<=m;i++)
{
cin>>a>>b>>w;//b-a<=w
add(a,b,w);
// add(a,b,w);
}
for(int i=1;i<=d;i++)
{
cin>>a>>b>>w;//a-b>=w -->b-a<=-w
add(b,a,-w);
// add(b,a,-w);
}
spfa(0);
int ans=spfa(1);
if(dis[n]==0x3f3f3f3f)
{
cout<<-2<<endl;
}else
cout<<dis[n];
return 0;
}
/*
hack data
4 1 1
1 4 10
2 3 20
correct -1
wrong 10
*/
Intervals
这题隐含条件就更多了
设s[k]表示0~k至少选出c个整数是
\(s[b_i]-s[a_i-1]>=c_i\)
\(s[k]-s[k-1]>=0\)
\(s[k]-s[k-1]<=1\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50005;
struct ac
{
int u,to,w,next;
}edge[N*2];
int m,n,head[N],cnt,dis[N],tot[N];bool vis[N];
void add(int u,int v,int w)
{
edge[++cnt].u=u;
edge[cnt].w=w;
edge[cnt].next=head[u];
edge[cnt].to=v;
head[u]=cnt;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void write(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
}
void spfa(int st)
{
memset(dis,-0x3f,sizeof(dis));
queue <int> q;
q.push(st);
dis[st]=0;vis[st]=1;
while(q.size())
{
int u=q.front();q.pop();vis[u]=0;
for(int i=head[u];i;i=edge[i].next)
{
int to=edge[i].to,w=edge[i].w;
if(dis[to]<dis[u]+w)
{
dis[to]=dis[u]+w;
// cout<<to<<" "<<dis[to]<<endl;
if(!vis[to])
{
q.push(to);
vis[to]=1;
}
}
}
}
}
int main()
{
n=read();
int a,b,c;
int st=100000,en=-1;
for(int i=1;i<=n;i++)
{
a=read();b=read();c=read();
add(a-1,b,c);
st=min(st,a-1),en=max(en,b);
}
for(int i=st;i<=en;i++)
{
add(i-1,i,0);
add(i,i-1,-1);
}
// for(int i=st;i<=en;i++)add(i,i+1,0);
spfa(st);
cout<<dis[en]<<endl;
return 0;
}
出纳员问题
出纳员问题
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50005;
struct ac
{
int u,to,w,next;
}edge[N*2];
int m,n,head[N],cnt,dis[N],tot[N],R[25],k[N],avi[N];bool vis[N];
void add(int u,int v,int w)
{
edge[++cnt].u=u;
edge[cnt].w=w;
edge[cnt].next=head[u];
edge[cnt].to=v;
head[u]=cnt;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void write(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
}
void clear()
{
memset(head,0,sizeof(head));
memset(edge,0,sizeof(edge));cnt=0;
memset(tot,0,sizeof(tot));
}
bool spfa(int st)
{
memset(dis,-0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(st);
dis[st]=0;vis[st]=1;
tot[st]++;
while(q.size())
{
int u=q.front();q.pop();vis[u]=0;
for(int i=head[u];i;i=edge[i].next)
{
int to=edge[i].to,w=edge[i].w;
if(dis[to]<dis[u]+w)
{
dis[to]=dis[u]+w;
// cout<<to<<" "<<dis[to]<<endl;
if(!vis[to])
{
tot[to]++;
q.push(to);
vis[to]=1;
if(tot[to]>n)return false;
}
}
}
}
return true;
}
void buildedge(int least)
{
for(int t=1;t<=8;t++)
{
add(t+16,t,R[t]-least);
}
for(int t=9;t<=24;t++)
{
add(t-8,t,R[t]);
}
add(0,24,least);
}
int main()
{
int T;
T=read();
while(T--)
{
memset(R,0,sizeof(R));
memset(k,0,sizeof(k));
memset(avi,0,sizeof(avi));
int sum=0;
for(int i=1;i<=24;i++)
{
R[i]=read();
sum+=R[i];
}
n=read();
for(int i=1;i<=n;i++)
{
k[i]=read();
k[i]++;avi[k[i]]++;
}
int i=n;
if(sum==0)
{
cout<<0<<endl;continue;
}
for(i=n;i>=0;i--)
{
clear();
for(int t=1;t<=24;t++)
{
add(t,t-1,-avi[t]);
add(t-1,t,0);
}
buildedge(i);
if(!spfa(0))
{
break;
}
}
if(i==n)
{
cout<<"No Solution"<<endl;
}
else
{
cout<<i+1<<endl;
}
}
return 0;
}