POJ1275 Cashier Employment 二分 + 差分约束

Posted mychael

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1275 Cashier Employment 二分 + 差分约束相关的知识,希望对你有一定的参考价值。

题目链接

POJ1275

题解

显然可以差分约束
我们记(W[i])(i)时刻可以开始工作的人数
(s[i])为前(i)个时刻开始工作的人数的前缀和

每个时刻的要求(r[i]),可以通过如下限制满足:
[s[i] - s[i - 8] ge r[i]]
[0 le s[i] - s[i - 1] le W[i]]

但是(i - 8)可能为负,回到上一天的时刻,导致区间不连续,不好处理
我们可以二分答案(sum)
(i < 8)的部分改为:
[s[i + 16] - s[i] le sum - R[i]]
再加一个
[s[24] - s[0] ge sum]
这样就可以了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 105,maxm = 1000005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == ‘-‘) flag = -1; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    return out * flag;
}
int h[maxn],ne;
struct EDGE{int to,nxt,w;}ed[maxm];
inline void build(int u,int v,int w){
    ed[++ne] = (EDGE){v,h[u],w}; h[u] = ne;
}
int n,R[50],W[50];
int d[maxn],vis[maxn],cnt[maxn];
int q[maxm],head,tail;
bool spfa(){
    for (int i = 0; i <= 24; i++) d[i] = -INF,vis[i] = false,cnt[i] = 0;
    d[0] = 0; q[head = tail = 0] = 0;
    int u;
    while (head <= tail){
        u = q[head++];
        vis[u] = false; cnt[u]++;
        if (cnt[u] >= 25) return false;
        Redge(u) if (d[to = ed[k].to] < d[u] + ed[k].w){
            d[to] = d[u] + ed[k].w;
            if (!vis[to]) vis[to] = true,q[++tail] = to;
        }
    }
    return true;
}
bool check(int sum){
    for (int i = 1; i <= 24; i++) if (R[i] > sum) return false;
    cls(h); ne = 0;
    for (int i = 1; i < 8; i++) build(i + 16,i,R[i] - sum);
    for (int i = 8; i <= 24; i++) build(i - 8,i,R[i]);
    for (int i = 1; i <= 24; i++){
        build(i - 1,i,0);
        build(i,i - 1,-W[i]);
    }
    build(0,24,sum);
    return spfa();
}
int main(){
    int T = read();
    while (T--){
        for (int i = 1; i <= 24; i++)
            R[i] = read(),W[i] = 0;
        n = read(); int x;
        REP(i,n){
            x = read() + 1;
            W[x]++;
        }
        int l = 0,r = n,mid,flag = false;
        while (l < r){
            mid = l + r >> 1;
            if (check(mid)) r = mid,flag = true;
            else l = mid + 1;
        }
        if (!flag) puts("No Solution");
        else printf("%d
",l);
    }
    return 0;
}










以上是关于POJ1275 Cashier Employment 二分 + 差分约束的主要内容,如果未能解决你的问题,请参考以下文章

图论(差分约束系统):POJ 1275 Cashier Employment

POJ 1275 - Cashier Employment

poj 1275 Cashier Employment - 差分约束 - 二分答案

POJ1275 Cashier Employment[差分约束系统 || 单纯形法]

POJ1275 Cashier Employment 二分 + 差分约束

POJ 1275-Cashier Employment(差分约束系统)