您的位置:首页 > 其它

poj 1275(差分约束)

2013-04-04 16:12 393 查看
题意:1天24小时,每个小时需要售货员人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判断是否有正环即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 25;
int n;
int r[maxn], t[maxn], s[maxn];
struct edge
{
int v, c;
edge(){}
edge(int v, int c):v(v), c(c){}
};
vector <edge> adj[maxn];
void build(int mid)
{
memset(adj, 0, sizeof(adj));
for (int i = 0; i <24; ++i)
{
adj[i].push_back(edge(i + 1, 0));
adj[i + 1].push_back(edge(i, -t[i+1]));
}
for (int i = 8; i <= 24; ++i)
{
adj[i - 8].push_back(edge(i, r[i]));
}
for (int i = 1; i <= 7; ++i)
{
adj[i+16].push_back(edge(i, r[i] - mid));
}
adj[0].push_back(edge(24, mid));
}
int dis[maxn],cnt[maxn];
bool relax(int u, int v, int c)
{
if (dis[v] < dis[u] + c)
{
dis[v] = dis[u] + c;
return true;
}
return false;
}
bool spfa(int src)
{
bool vis[maxn];
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < maxn ; ++i)
dis[i] = -inf;
dis[src] = 0;
vis[src] = 1;
queue <int> q;
q.push(src);
while (!q.empty())
{
int pre = q.front();q.pop();
vis[pre] = 0;
for (int i = 0; i < adj[pre].size(); ++i)
{
if(relax(pre, adj[pre][i].v, adj[pre][i].c) && !vis[adj[pre][i].v])
{
if((++cnt[adj[pre][i].v]) > 25) return false;
q.push(adj[pre][i].v);
vis[adj[pre][i].v] = 1;
}
}
}
return true;
}
int main()
{
int test;
scanf("%d", &test);
while(test--)
{
memset(r, 0, sizeof(r));
memset(t, 0, sizeof(t));
memset(s, 0, sizeof(s));
for (int i = 1; i <= 24; ++i)
scanf("%d", &r[i]);
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
int x;
scanf("%d", &x);
++t[x + 1];
}
int low = 0, high = n + 1, ans = -1;
while (high >= low)
{
int mid = (high + low) >> 1;
build(mid);
if(spfa(0))
{
ans = mid;
high = mid - 1;
}
else
low = mid + 1;
}
/*for (int i = 0; i <= n; ++ i)
{
build(i);
//cout<<i<<endl;
if(spfa(0))
{
ans = i;
break;
}
}*/
if(ans == -1)
printf("No Solution\n");
else
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: