BZOJ1070: [SCOI2007]修车(最小费用最大流,思维)
Description
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同
的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最
小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
Input
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人
员维修第i辆车需要用的时间T。
Output
最小平均等待时间,答案精确到小数点后2位。
Sample Input
3 2
1 4
Sample Output
HINT
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
Source
网络流的精彩之处就在于建图,这道题的建图方法就特别好玩。
首先,题目要求的是最小的顾客平均等待的时间,由于总的汽车数一定是n,所以我们只需要求出最小的总的等待时间就可以了。
由于每个人同一时间只能修1辆,每辆车修一次就够了(流量限制),用m个人修n次即可(流量守恒),有网络流的性质,而且求极值,所以想到用最小费用最大流解决。
但还有一个问题,边的权值只有一个,那如何合并时间(次序)与修车费用这两个维度呢?
由于可以同时工作,我们分别考虑每个人。假定 i 辆车是某人 倒数第 j 个修的,那么这辆车对总的等待时间的贡献就是 修理i的费用×j(修理时,有 j-1 辆车在等待其修理完成)
所以我们这样建图:
每个人i拆成多个点,表示这个人 倒数第k次修理车(k最大为n),对某个单点,与表示车辆j的点添加一条流量为1,权值为 k×cost[i][j]
为保证每辆车只修理一次,从表示车辆的点向汇点连一条流量为1的边即可
代码:
/*
* @FileName: /media/shan/Study/代码与算法/OJ(无法分类的题目)/BZOJ/1070/bzoj1070.cpp
* @Author: Pic
* @Created Time: 2017年11月21日 星期二 13时51分31秒
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn=;
const int INF=0x3f3f3f3f;
struct Edge
{
int from,to,cap,flow,cost;
Edge(){}
Edge(int f,int t,int c,int fl,int co):from(f),to(t),cap(c),flow(fl),cost(co){}
};
struct MCMF
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool inq[maxn]; //是否在队列
int d[maxn]; //Bellman_ford单源最短路径
int p[maxn]; //p[i]表从s到i的最小费用路径上的最后一条弧编号
int a[maxn]; //a[i]表示从s到i的最小残量 //初始化
void init(int n,int s,int t)
{
this->n=n, this->s=s, this->t=t;
edges.clear();
for(int i=;i<n;++i) G[i].clear();
} //添加一条有向边
void AddEdge(int from,int to,int cap,int cost)
{
edges.push_back(Edge(from,to,cap,,cost));
edges.push_back(Edge(to,from,,,-cost));
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} //求一次增广路
bool BellmanFord(int &flow, int &cost)
{
for(int i=;i<n;++i) d[i]=INF;
memset(inq,,sizeof(inq));
d[s]=, a[s]=INF, inq[s]=true, p[s]=;
queue<int> Q;
Q.push(s);
while(!Q.empty())
{
int u=Q.front(); Q.pop();
inq[u]=false;
int len=G[u].size();
for(int i=;i<len;++i)
{
Edge &e=edges[G[u][i]];
if(e.cap>e.flow && d[e.to]>d[u]+e.cost)
{
d[e.to]= d[u]+e.cost;
p[e.to]=G[u][i];
a[e.to]= min(a[u],e.cap-e.flow);
if(!inq[e.to]){ Q.push(e.to); inq[e.to]=true; }
}
}
}
if(d[t]==INF) return false;
flow +=a[t];
cost +=a[t]*d[t];
int u=t;
while(u!=s)
{
edges[p[u]].flow += a[t];
edges[p[u]^].flow -=a[t];
u = edges[p[u]].from;
}
return true;
} //求出最小费用最大流
int Min_cost()
{
int flow=,cost=;
while(BellmanFord(flow,cost));
return cost;
}
}MM;
int c[maxn][maxn];
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int m,n;
while(~scanf("%d%d",&m,&n)){
int s=n*m+n+;
int t=s+;
MM.init(t+,s,t);
for(int i=;i<n;i++){
for(int j=;j<m;j++){
scanf("%d",&c[i][j]);
}
}
for(int i=;i<m;i++){
for(int j=;j<n;j++){
for(int k=;k<n;k++){
MM.AddEdge(i*n+j,n*m+k,,c[k][i]*(n-j));
}
}
}
for(int i=;i<n*m;i++){
MM.AddEdge(s,i,,);
}
for(int i=n*m;i<n*m+n;i++){
MM.AddEdge(i,t,,);
}
int res=MM.Min_cost();
printf("%.2lf\n",res*1.0/n);
} return ;
}
点我点我
BZOJ1070: [SCOI2007]修车(最小费用最大流,思维)的更多相关文章
- BZOJ1070[SCOI2007]修车——最小费用最大流
题目描述 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待 ...
- BZOJ 1070: [SCOI2007]修车 [最小费用最大流]
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 4936 Solved: 2032[Submit][Status] ...
- BZOJ-1070 修车 最小费用最大流+拆点+略坑建图
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3624 Solved: 1452 [Submit][Status] ...
- [bzoj1070][SCOI2007]修车_费用流
修车 bzoj-1070 SCOI-2007 题目大意:有m个人要修n台车,每个工人修不同的车的时间不同,问将所有的车都修完,最少需要花费的时间. 注释:$2\le m\le 9$,$1\le n \ ...
- bzoj1070: [SCOI2007]修车(费用流)
1070: [SCOI2007]修车 题目:传送门 题解: 一道挺简单的费用流吧...胡乱建模走起 贴个代码... #include<cstdio> #include<cstring ...
- 2018.10.13 bzoj1070: [SCOI2007]修车(费用流)
传送门 费用流经典题目. 自我感觉跟TheWindy′sThe Windy'sTheWindy′s很像. 利用费用提前计算的思想来建图就行了. 代码: #include<bits/stdc++. ...
- bzoj 1070 [SCOI2007]修车(最小费用最大流)
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3515 Solved: 1411[Submit][Status] ...
- [BZOJ1070][SCOI2007]修车 费用流
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 6209 Solved: 2641[Submit][Status] ...
- 洛谷 P2053 [SCOI2007]修车(最小费用最大流)
题解 最小费用最大流 n和m是反着的 首先, \[ ans = \sum{cost[i][j]}*k \] 其中,\(k\)为它在当前技术人员那里,排倒数第\(k\)个修 我们可以对于每个技术人员进行 ...
随机推荐
- 怎样写一个Hello World!
Python 的 Hello, World! 应该是所有语言里面最简单的: print("Hello, World!")
- WP8的新功能-通过一个程序来启动另一个程序
Wp8对原来的WP7做了大量的优化...其中一个就包括Protocol Association,也就是通过uri来打开另外一个程序,这也就是说,我们可以做一个程序来启动另外一个程序了,如微信,QQ之类 ...
- @Html.ActionLink方法
Html.ActionLink:MVC提供的自动构造重写地址的方法,该方法有五个重载 1.Html.ActionLink("linkText","actionName&q ...
- VS显示方法引用
菜单栏 工具->选项->文本编辑器->所有语言->CodeLens 勾上即可
- python+django学习一
pycharm破解地址:https://blog.csdn.net/qq_32811489/article/details/78636049 按照视频写代码,记录关键的地方方便自己记忆, 视频教程地址 ...
- RabbitMq 开始<一>
power shell 执行: dotnet new console --name Send mv Send/Program.cs Send/Send.cs dotnet new console -- ...
- javaIO——LineNumberReader
LineNumberReader 是java字符流中的一员,它继承自 BufferedReader,只是在 BufferedReader 基础上,提供了对当前流位置所在文本行的标记记录.先来看看定义: ...
- vue-动态路由+动态组件+动态页面
动态路由 路由组件是vue-router 动态路由即从后端请求路由信息,然后转化生成路由信息.所以这里的关键是不会提前知道什么菜单对应什么组件,因此路由声明的时候不再是写死的组件,而是可替换的动态路径 ...
- Oracle---PL/SQL的学习
PL/SQL程序 一.定义 declare 说明部分 begin 语句序列(DML语句) exception 例外处理语句 end; 二. 变量和常量说明 a) 说明变量(char,varchar2, ...
- 【转】SpringBoot+SpringCloud实现登录用户信息在微服务之间的传递
实现思路: 1:准备一个ThreadLocal变量,供线程之间共享. 2:每个微服务对所有过来的Feign调用进行过滤,然后从请求头中获取User用户信息,并存在ThreadLocal变量中. 3:每 ...