【BZOJ】【1070】【SCOI2007】修车
网络流/费用流
好神奇的建模= =
关键就是把每个技术员拆成n个点,表示这个技术员倒数第几个修的车子。。
考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了。
而这个影响就是后面每个将要修理的车都多等待了time的时间。
说一下我的思考过程吧:(好混乱……)
对于每辆车只修一次,所以每辆车跟S连(1,0)边(表示流量为1,费用为0)。
然后每辆车的修车时间怎么算呢?每辆车都跟每个修理工连边,这是肯定的……但是还有等待啊,等待的时间怎么算呢?
倒过来考虑,假如我们现在有一个修理方案,修理工A的修理顺序是1、2、4、6、7,那么他修1号车对于总等待时间的贡献就是time[1][A]*5,因为后面四辆车还得等着嘛;以此类推,修4号车的cost为time[4][A]*3……即倒数第 j 辆车的修理时间cost为time[car[j]][A]*j
已知了修理方案我们怎么用费用流的模型来表示出来它呢?
我们可以把每个修理工拆开!将一个修理工拆成n个点,第 j 个点表示这个修理工按序修的倒数第 j 辆车,由这个点连向所有车,流量为1,cost就为time[ 这辆车 ][ 这个修理工 ]*j,那么刚刚的例子中,第1号车就连向了修理工A的倒数第5个点,2号车连着倒数第4个点……
如果最优方案中A修的车没有5辆?而是1、4、7?那第一辆车肯定就不会去连倒数第5个点了,因为是最小费用流嘛,它就会连到倒数第3个点,4号车就会连到倒数第二个点……
这样建图,其实是把所有的方案都枚举了出来,每种修理方案都对应着一个流!
UPD:2015-03-19 09:22:15
VFK:裸的二分图最小权匹配,用KM来写会更快……
/**************************************************************
Problem: 1070
User: Tunix
Language: C++
Result: Accepted
Time:464 ms
Memory:6012 kb
****************************************************************/ //BZOJ 1070
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
#define CC(a,b) memset(a,b,sizeof(a))
using namespace std;
int getint(){
int v=,sign=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') sign=-; ch=getchar();}
while(isdigit(ch)) {v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,INF=~0u>>;
const double eps=1e-;
/*******************template********************/
int n,m,ans,tim[][];
struct edge{int from,to,v,c;};
struct Net{
edge E[M];
int head[N],next[M],cnt;
void ins(int x,int y,int z,int c){
E[++cnt]=(edge){x,y,z,c};
next[cnt]=head[x]; head[x]=cnt;
}
void add(int x,int y,int z,int c){
ins(x,y,z,c); ins(y,x,,-c);
}
int from[N],Q[M],S,T,d[N];
bool inq[N];
bool spfa(){
int l=,r=-;
F(i,S,T) d[i]=INF;
d[S]=; Q[++r]=S; inq[S]=;
while(l<=r){
int x=Q[l++];
inq[x]=;
for(int i=head[x];i;i=next[i])
if (E[i].v && d[x]+E[i].c<d[E[i].to]){
d[E[i].to]=d[x]+E[i].c;
from[E[i].to]=i;
if(!inq[E[i].to]){
Q[++r]=E[i].to;
inq[E[i].to]=;
}
}
}
return d[T]!=INF;
}
void mcf(){
int x=INF;
for(int i=from[T];i;i=from[E[i].from])
x=min(x,E[i].v);
for(int i=from[T];i;i=from[E[i].from]){
E[i].v-=x;
E[i^].v+=x;
ans+=x*E[i].c;
}
// ans+=x*d[t];
}
void init(){
m=getint(); n=getint(); cnt=;
F(i,,n)
F(j,,m) tim[i][j]=getint();
S=; T=n+n*m+;
F(i,,n) add(S,i,,);
F(i,n+,n+n*m) add(i,T,,);
F(i,,n)
F(j,,m)
F(k,,n)//枚举这 第i辆车是第j个人修的第k辆
add(i,j*n+k,,(n-k+)*tim[i][j]);
ans=;
while(spfa()) mcf();
printf("%.2lf\n",double(ans)/n);
}
}G1;
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
G1.init();
return ;
}
1070: [SCOI2007]修车
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 3044 Solved: 1227
[Submit][Status][Discuss]
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
【BZOJ】【1070】【SCOI2007】修车的更多相关文章
- BZOJ 1070: [SCOI2007]修车 [最小费用最大流]
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 4936 Solved: 2032[Submit][Status] ...
- bzoj 1070: [SCOI2007]修车 费用流
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2785 Solved: 1110[Submit][Status] ...
- bzoj 1070 [SCOI2007]修车(最小费用最大流)
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3515 Solved: 1411[Submit][Status] ...
- [BZOJ 1070] [SCOI2007] 修车 【费用流】
题目链接:BZOJ - 1070 题目分析 首先想到拆点,把每个技术人员拆成 n 个点,从某个技术人员拆出的第 i 个点,向某辆车连边,表示这是这个技术人员修的倒数第 i 辆车.那么这一次修车对整个答 ...
- BZOJ 1070: [SCOI2007]修车(费用流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1070 题意: 思路: 神奇的构图. 因为排在后面的人需要等待前面的车修好,这里将每个技术人员拆成n个 ...
- bzoj 1070 [SCOI2007]修车——网络流(拆边)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1070 后面还有几辆车在这个人这儿修,自己这辆车的时间对总时间的贡献就要多乘上几倍. 所以可以 ...
- bzoj 1070 [SCOI2007]修车
最小费用最大流. 将每个技术人员拆成车数个点,技术人员i的第j个点代表技术人员i修的倒数第j辆车. 源点向所有技术人员点连一条容量为1费用为0的边. 所有技术人员点向所有车点连边:技术人员i的第j个点 ...
- BZOJ.1070.[SCOI2007]修车(费用流SPFA)
题目链接 /* 神tm看错题*2.. 假如人员i依次维修W1,W2,...,Wn,那么花费的时间是 W1 + W1+W2 + W1+W2+W3... = W1*n + W2*(n-1) + ... + ...
- 【刷题】BZOJ 1070 [SCOI2007]修车
Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使 ...
- bzoj 1070: [SCOI2007]修车【最小费用最大流】
一开始从客人角度想的,怎么建都不对 从一个修车工所接待的所有顾客花费的总时间来看,设一共有x个人,那么第一个修的对总时间的贡献是x*w1,第二个是(x-1)*w2-以此类推.所以把第i个修车工拆成n组 ...
随机推荐
- 【学习笔记】【C语言】进制
1. 什么是进制 是一种计数的方式,数值的表示形式 2. 二进制 1> 特点:只有0和1,逢2进1 2> 书写格式:0b或者0b开头 3> 使用场合:二进制指令\二进制文件,变量在内 ...
- 直播开始:'云榨汁机'诞生记--聊聊JavaScript中的'业务建模'
闭包是JavaScript中的一个重要特性,在之前的博文中,我们说闭包是一个'看似简单,其实很有内涵'的特性.当我们用JavaScript来实现相对复杂的业务建模时,我们可以如何利用'闭包'这个特性呢 ...
- hdu 1879 继续畅通工程
/************************************************************************/ /* hdu 1879 继续畅通工程 Time L ...
- java 自动装箱和自动拆箱
自动装箱 java执行Integer i = 100:编译器编译成Integer i = Integer.valueOf(100); Integer i = 100; //编译器编译成Integer ...
- JAVA多线程通信
JAVA多线程通信 package com.frank.thread; /** * author:pengyan * date:Jun 16, 2011 * file:ProducerAndCusto ...
- Codevs 1097 校门外的树
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米 ...
- Apache HTTP Server安装教程
Apache HTTP Server安装教程 Apache HTTP Server的官方网站是:http://httpd.apache.org/,可以从中下载最新版本的Apache HTTP Serv ...
- AngularJS中的MVC模式
MVC根据逻辑关系,把前端项目的代码分为三个层次 model:模型,就是业务数据,前端项目中就是JS变量. view:视图,就是业务数据在用户面前的展现,前端项目中就是HTML. controller ...
- IOS动画隐式,显式,翻页
// ViewController.m // IOS动画0817 // // Created by 张艳锋 on 15/8/17. // Copyright (c) 2015年 张艳锋. Al ...
- 《使用shell位置变量进行目录文件的备份小脚本》
今天才发现原来位置变量也可以玩的这么爽!! 这是使用位置变量进行文件目录备份:#!/bin/bashDATE=`date +%F` //日期以年月日输出tar czf $1.$DATE.tar.gz ...