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 }

 

posted @ 2016-05-13 15:09  WABoss  阅读(364)  评论(0编辑  收藏  举报