1070: [SCOI2007]修车

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)

思路:开始以为排序之后模拟贪心,但是车的数量太多...每次对于一个工人来说,并不是直接按照他修理车的最短时间给他分配车的,还要看里面各种..修车时间差与等待总时间等因素;所以要用到网络流构图,让计算机不断的调整选择方案(增广路模拟);即最小费用最大流问题;

暴力构图:每个工人可能修理的车的数量即为车的数量,并且每次修理车的时间并不只是输入的时间,因为对于同一个工人来说其前面修理的车的时间会累加到后面修车的时间里面;但是一般这样前面对后面产生的次数影响,并不是对当前的车去看它前面修了哪些车,然后把这些车的总时间加上自己的时间代价的,因为这样还要不断记录与修改修车的顺序。。与其后面每次来找前面的麻烦。。还不如前面修理的时候直接计算出对后面的影响~~ 即该车是同一个工人倒数第k次修的,那么这辆车的总代价就是k*time[i][j];这样就有了暴力拆点的依据了~~

暴力拆点:把每个工人拆成m个点,第k个点表示是倒数第k次修的该车,至于该车就修改每辆车与n*m个点连边,边的容量为1,表示只修一次。费用为time[i]][j]*k;至于与超级源点和汇点连边时,cap为1,但是费用记得要记为0;这样直接跑最大流即可;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MS0(a) memset((a),0,sizeof(a))
#define MSi(a) memset((a),0x3f,sizeof(a))
#define MS1(a) memset((a),-1,sizeof(a))
#define inf 0x3f3f3f3f
const int T = ;
const int M = ;
const int N = ;
int tot = ,head[N];
struct edge{
int from,to,Next,cap,cost;
}e[M<<];
void ins(int u,int v,int cap,int cost)
{
e[++tot].Next = head[u];// tot从2开始,之后增广边还是可以异或~~并且head并不需要设为-1.
e[tot].from = u, e[tot].to = v;
e[tot].cap = cap; e[tot].cost = cost;
head[u] = tot;
}
void insert(int u,int v,int cap,int cost)//把cap当成费用;之后增广路中只是改变flow;
{
ins(u,v,cap,cost);ins(v,u,,-cost);
}
int t[][],dis[N],vis[N],p[N];
queue<int> que;
int spfa()
{
MSi(dis);
que.push();
p[] = ;dis[] = ;
while(!que.empty()){
int u = que.front();que.pop();
vis[u] = ;
for(int d = head[u];d ;d = e[d].Next){
int v = e[d].to;
if(e[d].cap && dis[v] > dis[u] + e[d].cost){
dis[v] = dis[u]+e[d].cost;
p[v] = d;
if(!vis[v]){
que.push(v);
vis[v] = ;
}
}
}
}
if(dis[T] == inf) return ;
return ;
}
int ans;
int mcf()
{
int v = inf;
for(int d = p[T];d;d = p[e[d].from])
v = min(v,e[d].cap);
for(int d = p[T];d;d = p[e[d].from]){
e[d].cap -= v; e[d^].cap += v;
ans += e[d].cost;
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = ;i <= m;i++)
for(int j = ;j <= n;j++)
scanf("%d",&t[i][j]);
for(int i = ;i <= n;i++)
for(int j = ;j <= m;j++)
insert(,(i-)*m+j,,);
for(int i = n*m+;i <= n*m+m;i++)
insert(i,T,,);
for(int i = ;i <= n;i++)
for(int j = ;j <= m;j++)//第i个工人修的倒数第j辆车;
for(int k = ;k <= m;k++)
insert((i-)*m+j,n*m+k,,t[k][i]*j);
while(spfa()) mcf();
printf("%.2f",.*ans/m);
}

【BZOJ】1070: [SCOI2007]修车的更多相关文章

  1. BZOJ 1070: [SCOI2007]修车 [最小费用最大流]

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 4936  Solved: 2032[Submit][Status] ...

  2. bzoj 1070: [SCOI2007]修车 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2785  Solved: 1110[Submit][Status] ...

  3. bzoj 1070 [SCOI2007]修车(最小费用最大流)

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3515  Solved: 1411[Submit][Status] ...

  4. [BZOJ 1070] [SCOI2007] 修车 【费用流】

    题目链接:BZOJ - 1070 题目分析 首先想到拆点,把每个技术人员拆成 n 个点,从某个技术人员拆出的第 i 个点,向某辆车连边,表示这是这个技术人员修的倒数第 i 辆车.那么这一次修车对整个答 ...

  5. BZOJ 1070: [SCOI2007]修车(费用流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1070 题意: 思路: 神奇的构图. 因为排在后面的人需要等待前面的车修好,这里将每个技术人员拆成n个 ...

  6. bzoj 1070 [SCOI2007]修车——网络流(拆边)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1070 后面还有几辆车在这个人这儿修,自己这辆车的时间对总时间的贡献就要多乘上几倍. 所以可以 ...

  7. bzoj 1070 [SCOI2007]修车

    最小费用最大流. 将每个技术人员拆成车数个点,技术人员i的第j个点代表技术人员i修的倒数第j辆车. 源点向所有技术人员点连一条容量为1费用为0的边. 所有技术人员点向所有车点连边:技术人员i的第j个点 ...

  8. BZOJ.1070.[SCOI2007]修车(费用流SPFA)

    题目链接 /* 神tm看错题*2.. 假如人员i依次维修W1,W2,...,Wn,那么花费的时间是 W1 + W1+W2 + W1+W2+W3... = W1*n + W2*(n-1) + ... + ...

  9. 【刷题】BZOJ 1070 [SCOI2007]修车

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使 ...

  10. bzoj 1070: [SCOI2007]修车【最小费用最大流】

    一开始从客人角度想的,怎么建都不对 从一个修车工所接待的所有顾客花费的总时间来看,设一共有x个人,那么第一个修的对总时间的贡献是x*w1,第二个是(x-1)*w2-以此类推.所以把第i个修车工拆成n组 ...

随机推荐

  1. [Effective C++ --012]复制对象时勿忘其每一个成分

    引言: 在深拷贝和浅拷贝的理解中,我们知道了“拷贝构造函数”一词,并且也了解了它的构成. A(const A& r); // 形式有多种,在这里只列出一个 因此,在值传递的应用场景里,我们可以 ...

  2. sleep() wait() yield() join()用法与区别

    1.sleep()方法 在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”.不推荐使用. sleep()使当前线程进入阻塞状态,在指定时间内不会执行. 2.wait()方法 在其他线程调用 ...

  3. ajax的一部分知识

    jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数,请求方式(p ...

  4. Java中处理Linux信号量

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/5976361. ...

  5. Leetcode 102. Binary Tree Level Order Traversal(二叉树的层序遍历)

    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...

  6. angularjs的一些优化小技巧

    尽可能少调用 ng-repeat ng-repeat默认会创建很多监听器,所以在数据量很大的时候,这个非常消耗页面性能,我觉的只有在当需要经常更新数据列表的时候才需要用ng-repeat,要不然放那么 ...

  7. Base64 编码

    Base64 字母表 Base64 编码将一个 8 位字节序列拆成 6 位的片段,并为每个 6 位的片段分配一个字符,这个字符是 Base64 字母表中的 64 个字符之一. Wert Zeichen ...

  8. Android之Http网络编程(二)

    上一篇文章简单的介绍了Android中http的两种通信方式,并且分别用获取百度网页做了实例.但是在实际应用中,更多的是客户端通过请求的参数来实现在服务端的具体操作,并最终返回数据给客户端.因为我们不 ...

  9. XML文件的解析方式

    XML文件4种解析方式分别是:DOM解析,SAX解析,JDOM解析,DOM4J解析.1.基础方法:DOM:与平台无关的官方的解析方式.SAX:Java平台提供的基于事件驱动的解析方式.2.扩展方法(在 ...

  10. 实现ios屏幕的横竖屏自适应

    整理总结中... 刷新 可以通过 -setNeedsUpdateConstraints -layoutIfNeeded 两个方法来刷新约束的改变,使UIView重新布局, 和CoreGraphic的- ...