第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人
员维修第i辆车需要用的时间T。
思路:对每个顾客都建一个点,每个维修人员拆成n个点,代表是他修的第几辆车,这样子,由顾客连向维修人员的有向边,费用就是 等他的人数乘以他修车的时间。求费用流即可
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int ans; 7 int go[200005],tot,S,T,first[200005],next[200005],flow[200005]; 8 int cost[200005],c[200005],edge[200005],from[200005],a[500][500]; 9 int nodes,b[500][500],n,m,op[200005],dis[200005],vis[200005]; 10 int read(){ 11 int t=0,f=1;char ch=getchar(); 12 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();} 13 while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();} 14 return t*f; 15 } 16 void insert(int x,int y,int z,int l){ 17 tot++; 18 go[tot]=y; 19 next[tot]=first[x]; 20 first[x]=tot; 21 flow[tot]=z; 22 cost[tot]=l; 23 } 24 void add(int x,int y,int z,int l){ 25 insert(x,y,z,l);op[tot]=tot+1; 26 insert(y,x,0,-l);op[tot]=tot-1; 27 } 28 bool spfa(){ 29 for (int i=0;i<=T;i++) dis[i]=0x3f3f3f3f,vis[i]=0; 30 dis[S]=0; 31 int h=1,t=1; 32 c[1]=S; 33 while (h<=t){ 34 int now=c[h++]; 35 for (int i=first[now];i;i=next[i]){ 36 int pur=go[i]; 37 if (flow[i]&&dis[pur]>dis[now]+cost[i]){ 38 dis[pur]=dis[now]+cost[i]; 39 from[pur]=now; 40 edge[pur]=i; 41 if (vis[pur]) continue; 42 vis[pur]=1; 43 c[++t]=pur; 44 } 45 } 46 vis[now]=0; 47 } 48 return dis[T]!=0x3f3f3f3f; 49 } 50 void updata(){ 51 int mn=0x7fffffff; 52 for (int i=T;i!=S;i=from[i]){ 53 mn=std::min(mn,flow[edge[i]]); 54 } 55 for (int i=T;i!=S;i=from[i]){ 56 flow[edge[i]]-=mn; 57 flow[op[edge[i]]]+=mn; 58 ans+=mn*cost[edge[i]]; 59 } 60 } 61 int main(){ 62 m=read();n=read(); 63 for (int i=1;i<=n;i++){ 64 for (int j=1;j<=m;j++){ 65 a[i][j]=read(); 66 } 67 } 68 S=0,T=n*m+n+1; 69 for (int i=1;i<=n;i++) 70 add(S,i,1,0); 71 nodes=n; 72 for (int i=1;i<=m;i++) 73 for (int k=1;k<=n;k++) 74 b[i][k]=++nodes,add(nodes,T,1,0); 75 for (int i=1;i<=n;i++) 76 for (int j=1;j<=m;j++) 77 for (int k=1;k<=n;k++) 78 add(i,b[j][k],1,k*a[i][j]); 79 while (spfa()) updata(); 80 double Ans=(double)ans/n; 81 printf("%.2f\n",Ans); 82 }