poj3762 The Bonus Salary! (mcmf 区间K覆盖问题)
2016-08-14 23:53
267 查看
The Bonus Salary!
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次。
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 2694 | Accepted: 720 |
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; }
相关文章推荐
- popwondows简单用法
- Retrofit情景分析
- Java集群优化——dubbo+zookeeper构建高可用分布式集群
- 26最小公倍数 lowest common multiple
- python 开发简单爬虫 by CL(一)
- Leetcode 92. Reverse Linked List II (Medium) (cpp)
- one
- uva 572 Oil Deposits
- 在 Mac 端获取【网易云音乐】付费音乐的播放地址(注意下载要坚决支持正版!)
- Android 联系人数据库介绍以及对联系人的基本操作
- 灯泡的研究
- Android 联系人数据库介绍以及对联系人的基本操作
- 2016中国大学生程序设计竞赛 - 网络选拔赛
- 0utLook 2010打开后无法连接到CAS 阵列名
- SQL通配符
- go-并发
- 嵌入式学习--step10--实践篇--MPU6050
- 欢迎使用CSDN-markdown编辑器
- Torch学习笔记
- EJB 3会话bean与Spring的区别