#include<bits/stdc++.h>
using namespace std;
const int N = 1010, M = N * 23;
int T;
int h[N], e[M], ne[M], w[M], idx;
int n, m;
int dist[N];
bool st[N];
int num[N]; //记录这个点需要几个人
int r[N]; //记录这个点有几个人
int cnt[N];
int q[N];
void add(int a, int b, int c){
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx ++ ;
}
void build(int s24){
memset(h, -1, sizeof h);
idx = 0;
add(0, 24, s24), add(24, 0, -s24);
for(int i = 8; i <= 24; i ++ ) add(i - 8, i, r[i]); //这个时间段的员工数量不能小于r[i]
for(int i = 1; i <= 7; i ++ ) add(i + 16, i, r[i] - s24); //这个时间段的人数不应该
for(int i = 1; i <= 24; i ++ ){
add(i - 1, i, 0); //这个表示后一个时间段工作的人数大于第一个时间段
add(i, i - 1, -num[i]); //这里表示这个时间段可以多几个人工作
}
}
bool spfa(int s24){
build(s24);
memset(cnt, 0, sizeof cnt);
memset(dist, -0x3f, sizeof dist);
memset(st, 0, sizeof st);
int hh = 0, tt = 1;
dist[0] = 0;
q[0] = 0;
st[0] = true;
while(hh != tt){
int t = q[hh ++ ];
if(hh == N) hh = 0;
st[t] = false;
for(int i = h[t]; ~i; i = ne[i]){
int j = e[i];
if(dist[j] < dist[t] + w[i]){
dist[j] = dist[t] + w[i];
cnt[j] = cnt[t] + 1;
if(cnt[j] >= 25) return false; //如果存在环的话,咋不可能达成样例中所有条件,直接返回
if(!st[j]){
q[tt ++ ] = j;
if(tt == N) tt = 0;
st[j] = true;
}
}
}
}
return true;
}
int main()
{
cin>>T;
while(T -- ){
for(int i = 1; i <= 24; i ++ ){
cin>>r[i];
}
cin>>n;
memset(num, 0, sizeof num);
for(int i = 0; i < n; i ++ ){
int t;
cin>>t;
num[t + 1] ++ ;
}
bool flag = false;
for(int i = 0; i <= 1000; i ++ ){
if(spfa(i)){
cout<<i<<endl;
flag = true;
break;
}
}
if(!flag) puts("No Solution");
}
return 0;
}
AcWing 393. 雇佣收银员 题解(spfa算法负环做差分约束)
最新推荐文章于 2024-08-27 17:53:55 发布
本文详细解析AcWing在线编程平台的第393题——雇佣收银员。通过探讨如何利用SPFA(Shortest Path Faster Algorithm)算法处理存在负权边的最短路径问题,解决题目中的负环差分约束。文章深入浅出地阐述了算法思想和实现步骤,帮助读者理解并掌握这一算法的应用。
摘要由CSDN通过智能技术生成