您的位置:首页 > 其它

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

2016-01-31 11:19 477 查看


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

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

#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员工能够制造的产品种类有所区别。一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造。

我们用一个由0和1组成的m*n的矩阵A来描述每名员工能够制造哪些产品。矩阵的行和列分别被编号为1~m和1~n,Ai,j为1表示员工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, 1≤j≤Si+1。

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

Input

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

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

以下m行每行n 个整数描述矩阵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

第一轮day2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: