BZOJ 1070: [SCOI2007]修车

BZOJ 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)

Source

Solution

十分精巧的构图方式。
把一个工人拆成n个点,即有n*m个点,A[i][j]表示第i个工人,倒数第j个修的车。
因为修一个车只会影响到后面该工人要修的车的时间。所以跑一个最小费用流就行了。

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,x) for(int i=head[x];i;i=e[i].next)
#define mem(a,x) memset(a,x,sizeof(a))
typedef long long LL;
typedef double DB;
using namespace std;
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') f=(ch=='-')?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+(ch-'0'),ch=getchar();return f*x;
}
const int inf=0x3f3f3f3f,T=1001,S=0;
using namespace std;
int n,m,cnt=1,ans,l[61][10];
int d[1005],q[1005],from[1005],head[1005];
bool inq[1005];
struct edge {int from,to,next,c,v;} e[100001];
void ins(int u,int v,int r,int c) {e[++cnt]=(edge){u,v,head[u],c,r},head[u]=cnt;}
void insert(int u,int v,int r,int c) {ins(u,v,r,c),ins(v,u,0,-c);}
bool spfa() {
	fo(i,0,T) d[i]=inf;
	int l=0,r=1;
	d[S]=0,inq[S]=1,q[0]=S;
	while(l!=r) {
		int now=q[l++];if(l==T) l=0;
		rep(i,now) if(e[i].v&&d[e[i].to]>d[now]+e[i].c) {
			d[e[i].to]=d[now]+e[i].c;
			from[e[i].to]=i;
			if(!inq[e[i].to]) {
				inq[e[i].to]=1;
				q[r++]=e[i].to;if(r==T) r=0;
			}
		}
		inq[now]=0;
	}
	if(d[T]==inf) return 0;
	return 1;
}
void dfs() {
	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^1].v+=x,ans+=e[i].c*x;
}
void ek_spfa() {while(spfa()) dfs();}
void build() {
	fo(i,1,n*m) insert(S,i,1,0);
	fo(i,n*m+1,n*m+m) insert(i,T,1,0);
	fo(i,1,n) fo(j,1,m) fo(k,1,m) insert((i-1)*m+j,n*m+k,1,l[k][i]*j);
}
int main() {
	freopen("1070.in","r",stdin);
	n=read(),m=read();
	fo(i,1,m) fo(j,1,n) l[i][j]=read();
	build(),ek_spfa();
	printf("%.2lf",(double)ans/m);
	return 0;
}
原文地址:https://www.cnblogs.com/patricksu/p/8016211.html