• poj 1275(差分约束)


    题意:124小时,每个小时需要售货员人r[i]个(r[1]表示从0:00-1:00,,等等),n个工人应聘,每个人开始工作时间为st[i],都工作8个小时。问最少的应聘人数。

     

    分析:为了防止出现负数,在这里把标号设为1-24,并且设0为虚点。设x[i]是实际雇用的i时刻开始工作的员工数 ,r[i]是题目需要的i时刻正在工作的最少员工数.

    s[i] = x[1] + x[2] + …… + x[i] ,s[0]=0.
    s[i]表示1-i这段时间开始工作的员工数 
    再设t[i]表示i时刻开始工作的最多可以雇用的员工数 
    ∴有0 <= x[i] <= t[i] 
    即 0 <= s[i] - s[i-1] <= t[i] 
    由于是求最小值,所以用最长路 。
    则有:①s[i] - s[i-1] >= 0;②s[i-1] - s[i] >= -t[i] (1 <= i <= 24) 
    由于员工可以持续工作8个小时(r[i]i时刻正在工作的最少人数
    x[i-7] + x[i-6] + …… + x[i] >= r[i]i-7开始工作的人在i时刻也在工作,其他同理】 
    即:③s[i] - s[i-8] >= r[i] (8 <= i <= 24) 
    或者:(x[i+17] + …… + x[24]) + (x[1] + x[2] + …… + x[i]) >= r[i]; (i<=7
    则:s[24] - s[i+16] + s[i] >= r[i]; 
    整理一下:④s[i] - s[i+16] >= r[i] - s[24];(1 <= i <= 7) 

    显然④式跟一般的差分约束式子不太一样。因为s[24]是未知的。所以我们可以去找一个④的一个充分条件来代替④式,同时使得式子是符合差分约束形式的。

    即:⑤s[24] >= k 

    s[i] - s[i+16] >= r[i] - k

    显然满足①②③⑤⑥式的最小的k即为所求。枚举或二分k判断是否有正环即可。

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <queue>
      7 using namespace std;
      8 
      9 const int inf = 0x3f3f3f3f;
     10 const int maxn = 25;
     11 int n;
     12 int r[maxn], t[maxn], s[maxn];
     13 struct edge
     14 {
     15     int v, c;
     16     edge(){}
     17     edge(int v, int c):v(v), c(c){}
     18 };
     19 vector <edge> adj[maxn];
     20 void build(int mid)
     21 {
     22     memset(adj, 0, sizeof(adj));
     23     for (int i = 0; i <24; ++i)
     24     {
     25         adj[i].push_back(edge(i + 1, 0));
     26         adj[i + 1].push_back(edge(i, -t[i+1]));
     27     }
     28     for (int i = 8; i <= 24; ++i)
     29     {
     30         adj[i - 8].push_back(edge(i, r[i]));
     31     }
     32     for (int i = 1; i <= 7; ++i)
     33     {
     34         adj[i+16].push_back(edge(i, r[i] - mid));
     35     }
     36     adj[0].push_back(edge(24, mid));
     37 }
     38 int dis[maxn],cnt[maxn];
     39 bool relax(int u, int v, int c)
     40 {
     41     if (dis[v] < dis[u] + c)
     42     {
     43         dis[v] = dis[u] + c;
     44         return true;
     45     }
     46     return false;
     47 }
     48 bool spfa(int src)
     49 {
     50     bool vis[maxn];
     51     memset(vis, 0, sizeof(vis));
     52     memset(cnt, 0, sizeof(cnt));
     53     for (int i = 0; i < maxn ; ++i)
     54         dis[i] = -inf;
     55     dis[src] = 0;
     56     vis[src] = 1;
     57     queue <int> q;
     58     q.push(src);
     59     while (!q.empty())
     60     {
     61         int pre = q.front();q.pop();
     62         vis[pre] = 0;
     63         for (int i = 0; i < adj[pre].size(); ++i)
     64         {
     65             if(relax(pre, adj[pre][i].v, adj[pre][i].c) && !vis[adj[pre][i].v])
     66             {
     67                 if((++cnt[adj[pre][i].v]) > 25) return false;
     68                 q.push(adj[pre][i].v);
     69                 vis[adj[pre][i].v] = 1;
     70             }
     71         }
     72     }
     73     return true;
     74 }
     75 int main()
     76 {
     77     int test;
     78     scanf("%d", &test);
     79     while(test--)
     80     {
     81         memset(r, 0, sizeof(r));
     82         memset(t, 0, sizeof(t));
     83         memset(s, 0, sizeof(s));
     84         for (int i = 1; i <= 24; ++i)
     85             scanf("%d", &r[i]);
     86         scanf("%d", &n);
     87         for (int i = 1; i <= n; ++i)
     88         {
     89             int x;
     90             scanf("%d", &x);
     91             ++t[x + 1]; 
     92         }
     93         int low = 0, high = n + 1, ans = -1;
     94         while (high >= low)
     95         {
     96             int mid = (high + low) >> 1;
     97             build(mid);
     98             if(spfa(0))
     99             {
    100                 ans = mid;
    101                 high = mid - 1;
    102             }
    103             else
    104                 low = mid + 1;
    105         }
    106         /*for (int i = 0; i <= n; ++ i)
    107         {
    108             build(i);
    109             //cout<<i<<endl;
    110             if(spfa(0))
    111             {
    112                 ans = i;
    113                 break;
    114             }
    115         }*/
    116         if(ans == -1)
    117             printf("No Solution\n");
    118         else
    119             printf("%d\n", ans);
    120     }
    121     return 0;
    122 }

     

     

  • 相关阅读:
    codeforces 459 C. Pashmak and Buses(思维)
    poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)
    codeforces E. Phone Talks(dp)
    BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分+单点更新+区间求和+区间求最大值)
    SPOJ
    hdu 3966 Aragorn's Story(树链剖分+区间修改+单点查询)
    codeforces H. Queries for Number of Palindromes(区间dp)
    codeforces 245 D. Restoring Table(位运算+思维)
    codeforces 402 D. Upgrading Array(数论+贪心)
    codeforces 793 D. Presents in Bankopolis(记忆化搜索)
  • 原文地址:https://www.cnblogs.com/Missa/p/2999448.html
Copyright © 2020-2023  润新知