AcWing 393. 雇佣收银员 题解(spfa算法负环做差分约束)

本文详细解析AcWing在线编程平台的第393题——雇佣收银员。通过探讨如何利用SPFA(Shortest Path Faster Algorithm)算法处理存在负权边的最短路径问题,解决题目中的负环差分约束。文章深入浅出地阐述了算法思想和实现步骤,帮助读者理解并掌握这一算法的应用。
摘要由CSDN通过智能技术生成

AcWing 393. 雇佣收银员
请添加图片描述
请添加图片描述

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值