poj3762 The Bonus Salary! (mcmf 区间K覆盖问题)

来源:互联网 发布:windows ab 压力测试 编辑:程序博客网 时间:2024/06/01 09:30
The Bonus Salary!

Time Limit: 2000MSMemory Limit: 65536KTotal Submissions: 2694Accepted: 720

Description

In order to encourage employees’ productivity, ACM Company has made a new policy. At the beginning of a period, they give a list of tasks to each employee. In this list, each task is assigned a “productivity score”. After the first K days, the employee who gets the highest score will be awarded bonus salary.

Due to the difficulty of tasks, for task i-th:

  • It must be done from hh_Li : mm_Li : ss_Li to hh_Ri : mm_Ri : ss_Ri.
  • This range of time is estimated very strictly so that anyone must use all of this time to finish the task.

Moreover, at a moment, each employee can only do at most one task. And as soon as he finishes a task, he can start doing another one immediately.

XYY is very hard-working. Unfortunately, he’s never got the award. Thus, he asks you for some optimal strategy. That means, with a given list of tasks, which tasks he should do in the first K days to maximize the total productivity score. Notice that one task can be done at most once.

Input

The first line contains 2 integers N and K (1 ≤ N ≤ 2000, 0 ≤ K ≤ 100), indicating the number of tasks and days respectively. This is followed by N lines; each line has the following format:

hh_Li:mm_Li:ss_Li hh_Ri:mm_Ri:ss_Ri w

Which means, the i-th task must be done from hh_Li : mm_Li : ss_Li to hh_Ri : mm_Ri : ss_Ri and its productivity score is w. (0 ≤hh_Li, hh_Ri ≤ 23, 0 ≤mm_Li, mm_Ri, ss_Li, ss_Ri ≤ 59, 1 ≤ w ≤ 10000). We use exactly 2 digits (possibly with a leading zero) to represent hh, mm and ss. It is guaranteed that the moment hh_Ri : mm_Ri : ss_Ri is strictly later than hh_Li : mm_Li : ss_Li. 

Output

The output only contains a nonnegative integer — the maximum total productivity score.

Sample Input

5 2 
09:00:00 09:30:00 2
09:40:00 10:00:00 3
09:29:00 09:59:00 10
09:30:00 23:59:59 4
07:00:00 09:31:00 3

Sample Output

16

这道题就是一个区间K覆盖问题的模版把。。
感觉以后这种问题都可以转化为费用流来解决。
费用流建图:
离散化,然后对离散化之后的点相互之间连一条边,费用0,容量inf或者至少k都行。然后离散化之后的区间左右端点连一条边,费用-w(因为要求最大的,而我们的是mcmf),容量为1,表示只能选一次,然后连上超级源点超级汇点,容量均为k,费用为0。这里的容量不能为inf,因为要选k次。

#include<iostream>using namespace std;#include<cstdio>#include<cstring>#include<algorithm>#include<assert.h>#include<queue>const int maxn=5005;const int maxm=13000;const int inf=0x3f3f3f3f;int head[maxn];struct note {    int to,next,cap,flow,cost;} edge[maxm];struct notes {    int start,ends,nums;} in[2005];int n,m,top;int pre[maxn];int d[maxn];bool used[maxn];int que[maxm*100];inline void ADD(int u,int v,int f,int w) {    edge[top].cap=f;    edge[top].flow=0;    edge[top].to=v;    edge[top].cost=w;    edge[top].next=head[u];    head[u]=top++;    edge[top].cap=0;    edge[top].flow=0;    edge[top].to=u;    edge[top].cost=-w;    edge[top].next=head[v];    head[v]=top++;}bool spfa(int s,int t) {    memset(d,inf,sizeof(d));    memset(used,false,sizeof(used));    memset(pre,-1,sizeof(pre));    d[s]=0,used[s]=true;    int f=0,last=0;    que[last++]=s;    while(f<last) {        int now=que[f++];        used[now]=false;        for(int i=head[now]; ~i; i=edge[i].next) {            int to=edge[i].to;            if((edge[i].flow<edge[i].cap)&&(edge[i].cost+d[now]<d[to])) {                d[to]=d[now]+edge[i].cost;                pre[to]=i;                if(!used[to]) {                    used[to]=true;                    que[last++]=to;                }            }        }    }    return d[t]!=inf;}void mcmf(int s,int t,int& cost) {    cost=0;    int Min;    while(spfa(s,t)) {        Min=inf;        for(int i=pre[t]; ~i; i=pre[edge[i^1].to]) {            if(Min>(edge[i].cap-edge[i].flow)) {                Min=edge[i].cap-edge[i].flow;            }        }        for(int i=pre[t]; ~i; i=pre[edge[i^1].to]) {            edge[i].flow+=Min;            edge[i^1].flow-=Min;            cost+=edge[i].cost*Min;        }    }}int H[5105];int fuck(int val1,int val2,int val3) {    return val1*60*60+val2*60+val3;}void Init() {    top=0;    memset(head,-1,sizeof(head));}int main() {#ifdef tangge    freopen("3762.txt","r",stdin);#endif // tangge    int u,v,w;    while(~scanf("%d%d",&n,&m)) {        int s=0;        Init();        for(int i=0; i<n; ++i) {            scanf("%d:%d:%d",&u,&v,&w);            in[i].start=fuck(u,v,w);            scanf("%d:%d:%d",&u,&v,&w);            in[i].ends=fuck(u,v,w);            H[s++]=in[i].start;            H[s++]=in[i].ends;            scanf("%d",&in[i].nums);        }        sort(H,H+s);        int len=unique(H,H+s)-H;        int S=0,T=len+1;        ADD(S,1,m,0);        for(int i=1; i<len; ++i) {            ADD(i,i+1,m,0);        }        ADD(len,T,m,0);        for(int i=0; i<n; ++i) {            int pos1=lower_bound(H,H+len,in[i].start)-H+1;            int pos2=lower_bound(H,H+len,in[i].ends)-H+1;            ADD(pos1,pos2,1,-in[i].nums);        }        int cost;        mcmf(S,T,cost);        printf("%d\n",-cost);    }    return 0;}
1 0