【图论/差分约束】AcWing 393. 雇佣收银员
分析
这题就推一些柿子。
考虑时间点 安排了 人。
设时间点 最多来 个员工,我们有约束:。
然后我们还需要满足每个时间段被 人覆盖。
分个类:
- 时,
- ,
上面的约束形式显然不是二元的,考虑使用前缀和(即 )对式子进行变换,那么上面所有的约束等价于:
- 当 ,
- 当 ,有
- 当 ,有
可以发现上面的式子有些不是二元形式,对于一元的式子,例如 ,我们可以定义一个零点 ,那么满足 ,这样便可以进行建边(也就是 号点向 号点连接权为 的边)。
而对于三元的式子,其实就是最后一条式子,我们不妨固定(比如通过枚举)一元,这里考虑固定 。
但注意到 的意义就是我们决策的人数,显然,如果决策的人数为 时有解,那么 时也必然有解,所以我们可以对 的值进行二分,这样就可以将图建出来了。
// Problem: 雇佣收银员
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/395/
// Memory Limit: 10 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define x first
#define y second
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int N=30;
const int n=24;
vector<pii> g[N];
int R[N];
int lim[N];
void add(int u, int v, int w){
g[u].pb({v, w});
}
int d[N], cnt[N];
bool vis[N];
bool spfa(int x){
// build graph
rep(i,0,n) g[i].clear();
add(n-1, n, -x), add(n, n-1, x);
add(n, 0, 0);
rep(i,1,n-1) add(i-1, i, 0);
add(0, n, -lim[0]);
rep(i,1,n-1) add(i, i-1, -lim[i]);
add(n, 7, R[7]);
rep(i,8,n-1) add(i-8, i, R[i]);
rep(i,0,6) add(i+16, i, R[i]-x);
memset(d, 0xcf, sizeof d);
memset(vis, false, sizeof vis);
memset(cnt, 0, sizeof cnt);
d[n]=0;
queue<int> q;
q.push(n);
vis[n]=true;
while(q.size()){
int u=q.front(); q.pop();
vis[u]=false;
for(auto &[go, w]: g[u]){
if(d[go]<d[u]+w){
d[go]=d[u]+w;
if(!vis[go]){
if(++cnt[go]==n) return false;
vis[go]=true;
q.push(go);
}
}
}
}
return true;
}
signed main(){
int cs; cin>>cs;
while(cs--){
rep(i,0,n-1) read(R[i]);
rep(i,0,n-1) lim[i]=0;
int m; cin>>m;
rep(i,1,m){
int x; read(x);
lim[x]++;
}
int l=0, r=m;
while(l<r){
int mid=l+r>>1;
if(spfa(mid)) r=mid;
else l=mid+1;
}
if(!spfa(l)) puts("No Solution");
else cout<<d[n-1]<<endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】