BZOJ-1070 修车 最小费用最大流+拆点+略坑建图
2016-01-17 17:21
204 查看
1070: [SCOI2007]修车
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 3624 Solved: 1452
[Submit][Status][Discuss]
Description
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
Input
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
Output
最小平均等待时间,答案精确到小数点后2位。
Sample Input
2 2
3 2
1 4
Sample Output
1.50
HINT
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
Source
借鉴了一下黄学长的建图姿势:
把每个工人拆成N个点,一共N*M个点
超级源S连这N*M个点,容量为1,费用为0
超级汇T连N*M+(1~M)个点(车),容量为1,费用为0
把每个车都与每个拆成的点相连,容量为1,费用为t【k】【i】*j
很显然,每个工人同一时间只能洗一辆车,也只有一辆车能被洗,所以容量为0,至于费用,考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了。而这个影响就是后面每个将要修理的车都多等待了time的时间。
然后zkw一遍除以人数即可。
code:
感谢DCrusher神犇,全程观赏水题过程。
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 3624 Solved: 1452
[Submit][Status][Discuss]
Description
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
Input
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
Output
最小平均等待时间,答案精确到小数点后2位。
Sample Input
2 2
3 2
1 4
Sample Output
1.50
HINT
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
Source
这个题啊,开始看出来是最小费用最大流了,但不知道怎么建图,人傻的不行,于是第一遍尝试WA告终
借鉴了一下黄学长的建图姿势:
把每个工人拆成N个点,一共N*M个点
超级源S连这N*M个点,容量为1,费用为0
超级汇T连N*M+(1~M)个点(车),容量为1,费用为0
把每个车都与每个拆成的点相连,容量为1,费用为t【k】【i】*j
很显然,每个工人同一时间只能洗一辆车,也只有一辆车能被洗,所以容量为0,至于费用,考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了。而这个影响就是后面每个将要修理的车都多等待了time的时间。
然后zkw一遍除以人数即可。
code:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define inf 0x7fffffff int n,m; int pg[100][10]; int S,T; struct data{ int v,c,to,next; }edge[500010]; int head[500010],cnt=1; int h,t,q[500010]; int dis[500010]; bool mark[500010],visit[500010]; int ans; int read() { int x=0,f=1;char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } void add(int u,int v,int cap,int cost) { cnt++;edge[cnt].v=cap; edge[cnt].to=v;edge[cnt].c=cost; edge[cnt].next=head[u];head[u]=cnt; } void insert(int u,int v,int cap,int cost) { add(u,v,cap,cost);add(v,u,0,-cost); } void init() { n=read();m=read(); for (int i=1; i<=m; i++) for (int j=1; j<=n; j++) pg[i][j]=read(); } void make() { S=0,T=n*m+m+1; for (int i=1; i<=n*m; i++) insert(S,i,1,0); for (int i=n*m+1; i<=n*m+m; i++) insert(i,T,1,0); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) for (int k=1; k<=m; k++) insert((i-1)*m+j,n*m+k,1,pg[k][i]*j); } bool spfa() { memset(visit,false,sizeof(visit)); for (int i=S; i<=T; i++) dis[i]=inf; h=0,t=1; q[0]=T;visit[T]=1;dis[T]=0; while (h<t) { int now=q[h];h++;visit[now]=0; for (int i=head[now]; i; i=edge[i].next) if (edge[i^1].v && dis[now]-edge[i].c<dis[edge[i].to]) { dis[edge[i].to]=dis[now]-edge[i].c; if (!visit[edge[i].to]) { visit[edge[i].to]=1; q[t++]=edge[i].to; } } } return dis[0]!=inf; } int dfs(int loc,int low) { mark[loc]=true; if (loc==T) return low; int w,used=0; for (int i=head[loc]; i; i=edge[i].next) if (dis[edge[i].to]==dis[loc]-edge[i].c && edge[i].v && !mark[edge[i].to]) { w=dfs(edge[i].to,min(low-used,edge[i].v)); ans+=w*edge[i].c; edge[i].v-=w;edge[i^1].v+=w; used+=w;if (used==low) return low; } return used; } void zkw() { int tmp=0; while (spfa()) { mark[T]=1; while (mark[T]) { memset(mark,0,sizeof(mark)); tmp+=dfs(0,inf); } } } int main() { init(); make(); zkw(); printf("%.2f\n",(double)ans/m); return 0; }
感谢DCrusher神犇,全程观赏水题过程。
相关文章推荐
- NSOperationQueue
- LeetCode Combination Sum II
- 一种结合hudson的算法自动化测试构想
- 一种结合hudson的算法自动化测试构想
- 设计模式C#实现(十六)——中介者模式
- Python的文本数据
- windows server 2008 R2搭建***
- BZOJ 1532: [POI2005]Kos-Dicing|网络流
- next_permutation函数介绍
- VirtualBox中不能正常使用OpneGL的问题
- 在VMware虚拟机中安装CentOS 7
- [Java视频笔记] 知识目录总览
- Centos6.7换源
- 常用MS SQL数据查询-2016
- Thinkpad X230如何进入BIOS界面
- 匆匆--朱自清
- Android listview优化
- Codeforces 596 C Wilbur and Points
- RecyclerView的基本用法二--滚动时RecyclerView之外的布局联动
- bzoj3993: [SDOI2015]星际战争