POJ3686 The Windy's(最小费用最大流)
题目大概说要用m个工厂生产n个玩具,第i个玩具在第j个工厂生产要Zij的时间,一个工厂同一时间只能生成一个玩具,问最少的用时。
这题建的图不是很直观。。
- 源点向玩具连容量1费用0的边
- 将每个工厂拆成n个点,向汇点连容量1费用0的边
- 第i个玩具向第j个工厂拆的第k个点连容量1费用k*Zij的边
如此跑最小费用最大流。。。就是答案了。。画画图写写计算一下就能知道。。。。原谅我太懒。。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 2555 8 #define MAXM 2555*5555 9 10 struct Edge{ 11 int u,v,cap,cost,next; 12 }edge[MAXM]; 13 int head[MAXN]; 14 int NV,NE,vs,vt; 15 16 void addEdge(int u,int v,int cap,int cost){ 17 edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost; 18 edge[NE].next=head[u]; head[u]=NE++; 19 edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost; 20 edge[NE].next=head[v]; head[v]=NE++; 21 } 22 bool vis[MAXN]; 23 int d[MAXN],pre[MAXN]; 24 bool SPFA(){ 25 for(int i=0;i<NV;++i){ 26 vis[i]=0; d[i]=INF; 27 } 28 vis[vs]=1; d[vs]=0; 29 queue<int> que; 30 que.push(vs); 31 while(!que.empty()){ 32 int u=que.front(); que.pop(); 33 for(int i=head[u]; i!=-1; i=edge[i].next){ 34 int v=edge[i].v; 35 if(edge[i].cap && d[v]>d[u]+edge[i].cost){ 36 d[v]=d[u]+edge[i].cost; 37 pre[v]=i; 38 if(!vis[v]){ 39 vis[v]=1; 40 que.push(v); 41 } 42 } 43 } 44 vis[u]=0; 45 } 46 return d[vt]!=INF; 47 } 48 int MCMF(){ 49 int res=0; 50 while(SPFA()){ 51 int flow=INF,cost=0; 52 for(int u=vt; u!=vs; u=edge[pre[u]].u){ 53 flow=min(flow,edge[pre[u]].cap); 54 } 55 for(int u=vt; u!=vs; u=edge[pre[u]].u){ 56 edge[pre[u]].cap-=flow; 57 edge[pre[u]^1].cap+=flow; 58 cost+=flow*edge[pre[u]].cost; 59 } 60 res+=cost; 61 } 62 return res; 63 } 64 65 int main(){ 66 int t,n,m,a; 67 scanf("%d",&t); 68 while(t--){ 69 scanf("%d%d",&n,&m); 70 vs=n*m+n; vt=vs+1; NV=vt+1; NE=0; 71 memset(head,-1,sizeof(head)); 72 for(int i=0; i<n; ++i){ 73 addEdge(vs,i,1,0); 74 for(int j=0; j<m; ++j){ 75 scanf("%d",&a); 76 for(int k=0; k<n; ++k){ 77 addEdge(i,j+k*m+n,1,(k+1)*a); 78 } 79 } 80 } 81 for(int j=0; j<m; ++j){ 82 for(int k=0; k<n; ++k){ 83 addEdge(j+k*m+n,vt,1,0); 84 } 85 } 86 printf("%.6f\n",MCMF()*1.0/n); 87 } 88 return 0; 89 }