1. 程式人生 > >BZOJ 1070 拆點 費用流

BZOJ 1070 拆點 費用流

sca esp -- return memset limit turn pre print

1070: [SCOI2007]修車

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 5860 Solved: 2487
[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 把修車師傅拆成 n*m個修車師傅 然後具體 // 還是看這裏吧http://hzwer.com/2877.html #include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000;
const int M=5e5+88;
const int INF=0x3f3f3f3f;
int mp[88][11];
struct node{
int u,v,flow,cost,next;
}e[M];
int tot,head[N],pre[N],C[N],F[N],V[N],n,m;
void add(int u,int v,int flow,int cost){
e[tot].u=u;e[tot].v=v;e[tot].flow=flow;e[tot].cost=cost;e[tot].next=head[u];head[u]=tot++;
e[tot].u=v;e[tot].v=u;e[tot].flow=0;e[tot].cost=-cost;e[tot].next=head[v];head[v]=tot++;
}
int SPFA(int s,int t){
memset(pre,-1,sizeof(pre));
for(int i=1;i<=t+1;++i) F[i]=0,C[i]=INF,V[i]=0;
queue<int>Q;
Q.push(s);
C[0]=0,F[0]=INF,V[0]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();
V[u]=0;
for(int i=head[u];i+1;i=e[i].next){
int v=e[i].v,f=e[i].flow,c=e[i].cost;
if(f>0&&C[v]>C[u]+c) {
C[v]=C[u]+c;
pre[v]=i;
F[v]=min(f,F[u]);
if(!V[v]) V[v]=1,Q.push(v);
}
}
}
return F[t];
}
int MCMF(int s,int t){
int ans=0,temp;
while(temp=SPFA(s,t)){
for(int i=pre[t];i+1;i=pre[e[i].u]) {
ans+=temp*e[i].cost;
e[i].flow-=temp;
e[i^1].flow+=temp;
}
}
return ans;
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d",&m,&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
scanf("%d",&mp[i][j]);//mp[i][j],顧客--修車人員
int st=0,ed=m*n+n+1;
for(int i=1;i<=n*m;++i) add(0,i,1,0);
for(int i=n*m+1;i<=n*m+n;++i) add(i,ed,1,0);
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
for(int k=1;k<=n;++k)
add((i-1)*n+j,n*m+k,1,mp[k][i]*j);
int ct=MCMF(st,ed);
printf("%.2f\n",double(ct)/n);
}

BZOJ 1070 拆點 費用流