BZOJ 2245: [SDOI2011]工作安排( 费用流 )

 

费用流模板题..限制一下不同愤怒值的工作数就可以了。

---------------------------------------------------------------------------------------------

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
 
const int maxn = 259;
const int INF = 1000000000;
 
int m, n, t[maxn], w[maxn];
int S, T, V, d[maxn << 1], a[maxn << 1];
bool inq[maxn << 1];
deque<int> q;
 
struct edge {
int t, c, w;
edge *n, *r;
} E[maxn * maxn << 1], *pt = E, *H[maxn << 1], *p[maxn << 1];
 
inline void Add(int u, int v, int c, int w) {
pt->t = v, pt->c = c, pt->w = w, pt->n = H[u], H[u] = pt++;
}
inline void AddEdge(int u, int v, int c, int w) {
Add(u, v, c, w), Add(v, u, 0, -w);
H[u]->r = H[v], H[v]->r = H[u];
}
 
void Work() {
ll ans = 0;
for(; ; ) {
for(int i = 0; i < V; i++)
d[i] = INF, inq[i] = false;
q.push_front(S);
d[S] = 0, a[S] = INF;
while(!q.empty()) {
int x = q.front(); q.pop_front();
inq[x] = false;
for(edge* e = H[x]; e; e = e->n) if(d[e->t] > d[x] + e->w && e->c) {
d[e->t] = d[x] + e->w;
a[e->t] = min(a[x], e->c);
p[e->t] = e;
if(inq[e->t]) continue;
inq[e->t] = true;
if(!q.empty() && d[q.front()] > d[e->t]) {
q.push_front(e->t);
} else
q.push_back(e->t);
}
}
if(d[T] == INF) break;
ans += ll(a[T]) * d[T];
for(int x = T; x != S; x = p[x]->r->t)
p[x]->c -= a[T], p[x]->r->c += a[T];
}
printf("%lld\n", ans);
}
 
int main() {
scanf("%d%d", &m, &n);
S = m + n, T = S + 1, V = T + 1;
for(int i = 0; i < n; i++) {
int t;
scanf("%d", &t);
AddEdge(i, T, t, 0);
}
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++) {
int t;
scanf("%d", &t);
if(t) AddEdge(i + n, j, INF, 0);
}
t[0] = 0;
for(int i = 0; i < m; i++) {
int s, v = i + n;
scanf("%d", &s);
for(int j = 1; j <= s; j++) scanf("%d", t + j);
for(int j = 0; j <= s; j++) scanf("%d", w + j);
for(int j = 1; j <= s; j++)
AddEdge(S, v, t[j] - t[j - 1], w[j - 1]);
AddEdge(S, v, INF, w[s]);
}
Work();
return 0;
}

---------------------------------------------------------------------------------------------

2245: [SDOI2011]工作安排

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1245  Solved: 608
[Submit][Status][Discuss]

Description

你的公司接到了一批订单。订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件。公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别。一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造。

我们用一个由01组成的m*n的矩阵A来描述每名员工能够制造哪些产品。矩阵的行和列分别被编号为1~m1~nAi,j1表示员工i能够制造产品j,为0表示员工i不能制造产品j

如果公司分配了过多工作给一名员工,这名员工会变得不高兴。我们用愤怒值来描述某名员工的心情状态。愤怒值越高,表示这名员工心情越不爽,愤怒值越低,表示这名员工心情越愉快。员工的愤怒值与他被安排制造的产品数量存在某函数关系,鉴于员工们的承受能力不同,不同员工之间的函数关系也是有所区别的。

对于员工i,他的愤怒值与产品数量之间的函数是一个Si+1段的分段函数。当他制造第1~Ti,1件产品时,每件产品会使他的愤怒值增加Wi,1,当他制造第Ti,1+1~Ti,2件产品时,每件产品会使他的愤怒值增加Wi,2……为描述方便,设Ti,0=0,Ti,si+1=+,那么当他制造第Ti,j-1+1~Ti,j件产品时,每件产品会使他的愤怒值增加Wi,j 1jSi+1

你的任务是制定出一个产品的分配方案,使得订单条件被满足,并且所有员工的愤怒值之和最小。由于我们并不想使用Special Judge,也为了使选手有更多的时间研究其他两道题目,你只需要输出最小的愤怒值之和就可以了。

Input

第一行包含两个正整数mn,分别表示员工数量和产品的种类数;

第二行包含个正整数,第i个正整数为Ci

以下m行每行个整数描述矩阵A

下面m个部分,第i部分描述员工i的愤怒值与产品数量的函数关系。每一部分由三行组成:第一行为一个非负整数Si,第二行包含Si个正整数,其中第j个正整数为Ti,j,如果Si=0那么输入将不会留空行(即这一部分只由两行组成)。第三行包含Si+1个正整数,其中第j个正整数为Wi,j

Output

仅输出一个整数,表示最小的愤怒值之和。

Sample Input


2 3

2 2 2

1 1 0

0 0 1

1

2

1 10

1

2

1 6

Sample Output

24

HINT

Source

 

posted @ 2016-01-31 11:19  JSZX11556  阅读(218)  评论(0编辑  收藏  举报