BZOJ 1070: [SCOI2007]修車
阿新 • • 發佈:2017-10-28
line 小數 con 題解 inf cpp pop 進行 geo
1070: [SCOI2007]修車
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 6231 Solved: 2652
[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)表示i員工倒數第j輛修的車,每輛車向這些點連邊,表示i員工倒數第j輛修這輛車,流量為1,費用為i*x,x為該員工修這輛車的時間,乘i是因為倒數第i個修這輛車,那麽對後i-1輛車都會多x的等待時間,會產生(i-1)*x的代價,所以總代價為i*x。
源點向每輛車連邊,流量為1,費用為0,每個點(i,j)向匯點連邊,流量為1,費用為0。
求最小費用最大流即可。
代碼
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #include<queue> using namespace std; const int N=65,M=10,inf=0x3f3f3f3f; int m,n,s,t,k,ans; int head[N*M],vis[N*M],dis[N*M],cur[N*M],from[N*M]; struct edge{ int u,v,flow,cost,next; }e[N*N*M*4]; void addedge(int u,int v,int flow,int cost){ e[k]=(edge){u,v,flow,cost,head[u]}; head[u]=k++; e[k]=(edge){v,u,0,-cost,head[v]}; head[v]=k++; } queue<int>q; bool spfa(){ for(int i=s;i<=t;i++){ vis[i]=0; dis[i]=inf; from[i]=-1; } dis[s]=0; q.push(s); vis[s]=1; int u,v,flow,cost; while(!q.empty()){ u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=e[i].next){ v=e[i].v,flow=e[i].flow,cost=e[i].cost; if(flow&&dis[u]+cost<dis[v]){ dis[v]=dis[u]+cost; from[v]=i; if(!vis[v]){ q.push(v); vis[v]=1; } } } } if(dis[t]!=inf)return true; return false; } void mcf(){ while(spfa()){ int x=inf; for(int i=from[t];i!=-1;i=from[e[i].u]) x=min(x,e[i].flow); for(int i=from[t];i!=-1;i=from[e[i].u]){ e[i].flow-=x; e[i^1].flow+=x; ans+=e[i].cost*x; } } } int main(){ memset(head,-1,sizeof(head)); scanf("%d%d",&m,&n); s=0,t=n+n*m+1; for(int i=1;i<=n;i++){ addedge(s,i,1,0); } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ addedge(i*n+j,t,1,0); } } int x; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&x); for(int k=1;k<=n;k++){ addedge(i,j*n+k,1,x*k); } } } mcf(); printf("%.2lf\n",(double)ans/n); return 0; }
BZOJ 1070: [SCOI2007]修車