bzoj 1070修车

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3865  Solved: 1581
[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)

 
最小费用最大流
时间的先后不好维护怎么办,讲工人拆成n个点,每个点表示第几个修当前这辆车。考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了
所以只需要将费用乘以k。然后每辆车向每个工人的每个点连费用不同的边,就可以轻松解决时间先后关系的问题。
 
方法:时间先后对费用有影响,将时间拆出来,分别考虑,讨论当前次序的费用,可以解决时间或次序的先后问题
 
注意:不要把n,m读反
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1020
#define maxm 100020
#define inf 0x3f3f3f3f

struct node{
	int to,next,f,ct,from;
}e[maxm * 2];
int head[maxn],cnt = 1,maxflow,mincost,dis[maxn],src,sink;
int q[maxn * 10],hh,tt,inq[maxn],prev[maxn];
int n,m;
int _time[100][100];
double ans;

inline void adde(int x,int y,int c,int ct){
	e[++cnt].to = y;
	e[cnt].from = x;
	e[cnt].next = head[x];
	e[cnt].f = c;
	e[cnt].ct = ct;
	head[x] = cnt;
	e[++cnt].to = x;
	e[cnt].from = y;
	e[cnt].next = head[y];
	e[cnt].f = 0;
	e[cnt].ct = -ct;
	head[y] = cnt;
}
inline bool spfa(){
	memset(dis,0x3f,sizeof(dis));
	tt = hh = 0;
	q[tt++] = src;
	dis[src] = 0;
	inq[src] = 1;
	while ( hh < tt ){
		int now = q[hh++];
		inq[now] = 0;
		for (int i = head[now] ; i ; i = e[i].next){
			if ( e[i].f && dis[e[i].to] > dis[now] + e[i].ct ){
				dis[e[i].to] = dis[now] + e[i].ct;	
				prev[e[i].to] = i;
				if ( !inq[e[i].to] ) q[tt++] = e[i].to , inq[e[i].to] = 1;
			}
		}
	}
	return dis[sink] < inf;
}
int dfs(){
	int delta = inf , x = sink;
	while ( x != src ){
		delta = min(delta,e[prev[x]].f);
		x = e[prev[x]].from;
	}
	x = sink;
	while ( x != src ){
		e[prev[x]].f -= delta;
		e[prev[x] ^ 1].f += delta;
		x = e[prev[x]].from;
	}
	return delta;
}
void init(){
	for (int i = 1 ; i <= n ; i++) adde(i,sink,1,0);
	for (int i = 1 ; i <= m ; i++)
		for (int j = 1 ; j <= n ; j++){
			adde(src,n + (i - 1) * n + j,1,0);
		}
	for (int i = 1 ; i <= n ; i++){
		for (int j = 1 ; j <= m ; j++){
			for (int k = 1 ; k <= n ; k++){
				adde(n + (j - 1) * n + k,i,1,_time[j][i] * (n - k + 1));		
			}
		}
	}
}
int main(){
	scanf("%d %d",&m,&n);
	src = n * m + n + 1 , sink = src + 1;
	for (int i = 1 ; i <= n ; i++){
		for (int j = 1 ; j <= m ; j++){
			scanf("%d",&_time[j][i]);
		}
	}
	init();
	while ( spfa() ){
		mincost += dfs() * dis[sink];
	}
	ans = (double)mincost/(double)n;
	printf("%.2lf\n",ans);
	return 0;
}

  

posted @ 2016-03-10 20:12  zhangqingqi  阅读(143)  评论(0编辑  收藏  举报