POJ 1275 Cashier Employment(差分约束)

http://poj.org/problem?id=1275

题意 : 一家24小时营业的超市,要雇出纳员,需要求出超市每天不同时段需要的出纳员数,午夜只需一小批,下午需要多些,希望雇最少的人,给出每小时需要的出纳员的最少数量,R(0),R(1),...,R(23)。R(0)表示从午夜到凌晨1:00所需要出纳员的最少数目;R(1)表示凌晨1:00到2:00之间需要的;以此类推。这些数据每一天都是相同的。有N人申请这工作,申请者 i ,从一个特定的时刻开始连续工作恰好8小时。定义ti(0<=ti<=23)为上面提到的开始时刻,也就是说,如果第i个申请者被录用,他)将从 ti 时刻开始连续工作8小时。

思路 :差分约束,挺难的,看了好多人的题解,才稍微懂一些了,http://972169909-qq-com.iteye.com/blog/1185527,这个神写的不错,,,还有黑书上也有解释

其实说的有点那啥,我一开始也还是没怎么看懂

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>

using namespace std;

const int INF = 9999999 ;
struct node
{
    int u,v,w ;
    int next ;
} map[250] ;
bool flag[25] ;
int cnt,pre[25],cntt[25],dist[25] ;
int r[25],t[26] ;

void addedge(int u,int v,int w)
{
    map[cnt].v = v ;
    map[cnt].w = w ;
    map[cnt].next = pre[u] ;
    pre[u] = cnt++ ;
}

void Init()
{
    cnt = 0 ;
    memset(pre,-1,sizeof(pre)) ;
    memset(cntt,0,sizeof(cntt)) ;
    memset(flag,false,sizeof(flag)) ;
}

bool spfa(int start)
{
    queue<int >Q ;
    for(int i = 0 ; i < 25 ; i++)
        dist[i] = -INF ;
    dist[start] = 0 ;
    Q.push(start) ;
    flag[start] = true ;
    while(!Q.empty())
    {
        int u = Q.front() ;
        Q.pop() ;
        if(++cntt[u] > 24)
            return false ;
        flag[u] = false ;
        for(int i = pre[u] ; i + 1 ; i = map[i].next)
        {
            int v = map[i].v ,w = map[i].w;
            if(dist[v] < dist[u] + w)
            {
                dist[v] = dist[u] + w ;
                if(!flag[v])
                {
                    flag[v] = true ;
                    Q.push(v) ;
                }
            }
        }
    }
    return true ;
}
int main()
{
    int T ;
    scanf("%d",&T) ;
    while(T--)
    {
        for(int i = 1 ; i <= 24 ; i++)
            scanf("%d",&r[i]) ;
        int N ,s;
        scanf("%d",&N) ;
        memset(t,0,sizeof(t)) ;
        for(int i = 0 ; i < N ; i++)
        {
            scanf("%d",&s) ;
            t[s + 1]++ ;
        }
        int low = 0 ,high = N ;
        bool flagg = false ;
        while(low < high)
        {
            Init() ;
            int mid = (low+high)>>1 ;
            for(int i = 1 ; i <= 24 ; i++)
            {
                addedge(i-1,i,0) ;
                addedge(i,i-1,-t[i]) ;
            }
            for(int i = 8 ; i <= 24 ; i++)
                addedge(i-8,i,r[i]) ;
            for(int i = 1 ; i <= 7 ; i++)
                addedge(i+16,i,r[i]-mid) ;
            addedge(0,24,mid) ;
            if(spfa(0))
            {
                high = mid ;
                flagg = true ;
            }
            else low = mid+1 ;
        }
        if(flagg)
            printf("%d
",high) ;
        else printf("No Solution
") ;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/luyingfeng/p/3542425.html