您的位置:首页 > 其它

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

2016-08-14 23:53 267 查看
The Bonus Salary!

Time Limit: 2000MSMemory Limit: 65536K
Total 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.
InputThe 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. 
OutputThe output only contains a nonnegative integer — the maximum total productivity score.
Sample Input5 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 Output16

这道题就是一个区间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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: