BZOJ1070: [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
3 2
1 4
Sample Output
1.50
HINT
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
将每个技术人员拆成n个点,分别表示由这个技术人员按顺序第几个修理该车。
然后二分图完美匹配就行。
#include<cstdio> #include<cctype> #include<queue> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=710; const int maxm=200010; const int inf=1e9; struct ZKW { long long cost,ans; int n,m,s,t,first[maxn],next[maxm]; int d[maxn],inq[maxn]; struct Edge {int from,to,flow,cost;}edges[maxm]; void init(int n) { this->n=n;m=0; memset(first,-1,sizeof(first)); } void AddEdge(int u,int v,int w,int c) { edges[m]=(Edge){u,v,w,c};next[m]=first[u];first[u]=m++; edges[m]=(Edge){v,u,0,-c};next[m]=first[v];first[v]=m++; } deque<int> Q; int BFS() { rep(i,1,n) d[i]=inf; Q.push_front(t);d[t]=0; while(Q.size()) { int x=Q.front();Q.pop_front();inq[x]=0; ren { Edge& e=edges[i^1]; if(e.flow&&d[e.from]>d[x]+e.cost) { d[e.from]=d[x]+e.cost; if(!inq[e.from]) { if(Q.size()&&d[e.from]<=d[Q.front()]) Q.push_front(e.from); else Q.push_back(e.from); inq[e.from]=1; } } } } rep(i,0,m-1) edges[i].cost+=d[edges[i].to]-d[edges[i].from]; cost+=d[s];return d[s]!=inf; } int vis[maxn]; int DFS(int x,int a) { if(x==t||!a) {ans+=cost*a;return a;} int flow=0,f;vis[x]=1; ren { Edge& e=edges[i]; if(e.flow&&!e.cost&&!vis[e.to]&&(f=DFS(e.to,min(a,e.flow)))) { e.flow-=f;edges[i^1].flow+=f; flow+=f;a-=f;if(!a) break; } } return flow; } long long solve(int s,int t) { this->s=s;this->t=t;ans=cost=0; while(BFS()) do memset(vis,0,sizeof(vis));while(DFS(s,inf)); return ans; } }sol; int main() { int m=read(),n=read(); int S=(m+1)*n+1,T=S+1;sol.init(T); rep(i,1,n) sol.AddEdge(S,i,1,0); rep(i,n+1,S-1) sol.AddEdge(i,T,1,0); rep(i,1,n) rep(j,1,m) { int val=read(); rep(k,1,n) sol.AddEdge(i,j*n+k,1,val*k); } printf("%.2lf\n",sol.solve(S,T)*1.0/n); return 0; }