poj 1275 Cashier Employment(差分约束#6)

此题约束条件较多。

 

 #include <cstdio>
#include <algorithm>
#include <cstdlib> 
#include <cstring> 
#define N 30 
#define M 100 
#define MAXQ 10000 
using namespace std; 
const int inf = (-1u >> 1); 
int R[24], t[24];
int s[N];
int d[N], first[N];
int u[M], v[M] , w[M], next[M]; 
bool inq[N];
int cnt[N]; 
int e;
int q[MAXQ]; 

void addE(int x, int y, int c)
{
      next[e] = first[x], first[x] = e;
      u[e] = x, v[e] = y;
      w[e] = c; 
      e++;
}
void init(int sum)
{ 
         e = 0;
         for (int i = 0; i <= 24; i++)
              first[i] = -1;
         for (int i = 0; i < 16; i++)
         { 
              addE(i, i + 8, R[i + 8]);
         } 
         for (int i = 16; i < 24; i++)
         { 
              addE(i, (i + 8)%24, R[(i + 8)% 24] - sum);
         }
         for (int i = 0; i < 23; i++)
         {
             addE(i, i + 1, 0);
             addE(i + 1, i, -t[i + 1]); 
         }
         addE(24, 0, 0);
         addE(0, 24, -t[0]); 
         addE(24, 23, sum);
} 
      

bool SPFA(int s, int n, int sum)
{
       for (int i = 0; i < n; i++)d[i] =  -inf;
       memset(cnt, 0, sizeof(cnt)); 
       d[s] = 0;
       int qs, qe; 
       qs = qe = 0; 
       for (int i = 0; i < n; i++)inq[i] = false; 
       q[qe++] = s; 
       while (qs < qe)
       {
              int x = q[qs++]; 
              inq[x] = false;
              for (int e = first[x]; e != -1; e = next[e])if (d[v[e]] < d[u[e]] + w[e])
              {
                    d[v[e]] = d[u[e]] + w[e]; 
                    if (!inq[v[e]])
                    {
                              inq[v[e]] = true;
                              q[qe++] = v[e];
                              if (++cnt[v[e]] >= n)return false; 
                    }
              }
       }
       return true;
} 


int main()
{
      int ca;
      scanf("%d", &ca);
      int m;
  //   FILE* fp = fopen("in.txt", "r");  
      while (ca--)
      {
             for (int i = 0; i < 24; i++)
             { 
                scanf( "%d", R + i);
             } 
             scanf( "%d", &m);
             int tmp;
             memset(t, 0, sizeof(t)); 
             for (int i = 0; i < m; i++) 
             { 
                  scanf( "%d", &tmp);
                  t[tmp]++;
             }
             bool flag = false; 
             int l = 0, r = m + 1;
             int mid , ans = -1; 
             while (l  + 1 < r) 
             { 
                     mid = ((l + r) / 2); 
                     init(mid);
                     flag = SPFA(24, 25, mid); 
                     if (flag)
                          r = mid, ans = mid;
                     else l = mid;  
             }
             if ( ans > 0 && ans < m + 1)printf("%d\n", ans);
             else puts("No Solution");
      }
      return 0;
} 
              
              
              
              
              


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值