POJ 3686 The Windy's
题目大意:
有n个订单m个车间,每个车间均可以单独完成任何一个订单。每个车间完成不同订单的时间是不同的。不会出现两个车间完成同一个订单的情况。给出每个订单在某个车间完成所用的时间。问订单完成的平均时间是多少。
解题思路:
1、这个题在建图上有一些需要思考很长时间的地方。因为每个订单所消耗的时间是车间完成订单的时间加上订单等待的时间。我们设在车间A需要完成k个订单,消耗的总时间是t1+(t1+t2)+(t1+t2+t3)……转换一下就是t1*k+t2*(k-1)+t3*(k-3)……我们就找到了规律:当第i个订单在第j个车间是倒数第k个任务时,总消耗时间需要加上订单i在车间对应消耗时间的k倍。
2、建图的时候记得用负值来建图,这样顶标数组初始化成0就行了。因为不会有比0大的值出现。
3、结果出来后取相反数,然后除以n来得到最后的结果。
下面是代码:
#include <stdio.h> #include <string.h> const int Maxn = 55; const int Maxm = Maxn*Maxn; const int inf = 1<<30; int n,m,t[Maxn][Maxn],w[Maxm][Maxm],km1[Maxm],km2[Maxm],pre[Maxm],d; bool visx[Maxm],visy[Maxm]; void init() { memset(pre,-1,sizeof(pre)); memset(km1,0,sizeof(km1)); memset(km2,0,sizeof(km2)); for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { scanf("%d",&t[i][j]); } } for(int i= 0; i<n; i++) { for(int j = 0; j<m; j++) { for(int k=0; k<n; k++) { w[i][j+k*m]=-(t[i][j]*(k+1)); } } } m*=n; } bool dfs(int src) { visx[src]=true; for(int i=0; i<m; i++) { if(!visy[i]) { int t=km1[src]+km2[i]-w[src][i]; if(!t) { visy[i]=true; if(pre[i]==-1||dfs(pre[i])) { pre[i]=src; return true; } } else if(d>t)d=t; } } return false; } double KM() { for(int i=0; i<n; i++) { while(1) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); d=inf; if(dfs(i))break; for(int j=0;j<n;j++) { if(visx[j]) { km1[j]-=d; } } for(int j=0;j<m;j++) { if(visy[j]) { km2[j]+=d; } } } } double ans=0; for (int i=0; i<m; i++) { if (pre[i]!=-1) ans+=w[pre[i]][i]; } return -ans; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); printf("%.6lf\n",KM()/(n*1.0)); } return 0; }