poj 2516(最小费用流)

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <queue>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <cstring>
  7 using namespace std;
  8 
  9 #define inf 0x3f3f3f3f
 10 
 11 int supply[55],demand[55];//某种商品的提供量和需求量
 12 int dis[110],pre[110],s,t;//s为超级源点,t为超级汇点
 13 int order[55][55];//第i个商店对第j种物品的需求
 14 int store[55][55];//第i个供应站对第j个物品的存储量
 15 int flow[110][110],cap[110][110];//边的流量,容量
 16 int cost[55][55][55];//cost[k][j][i]第k种商品从第j个供应站运到第i个商店的花费
 17 int kcost[110][110];//每件商品在某一条边的花费。从供应站到商店方向
 18 int vis[110];
 19 int n,m,k;
 20 
 21 int spfa()
 22 {
 23     queue<int>q;
 24     memset(vis,0,sizeof(vis));
 25     memset(pre,-1,sizeof(pre));
 26     q.push(s);
 27     fill(&dis[1],&dis[n+m+2],inf);//dis[1----n+m+1]==inf
 28     dis[s]=0;
 29     vis[s]=1;
 30     while(!q.empty())
 31     {
 32         int cur=q.front();q.pop();
 33         vis[cur]=0;
 34         for(int i=0;i<=n+m+1;i++)
 35         {
 36             if(cap[cur][i] >flow[cur][i] && dis[i] > dis[cur] + kcost[cur][i])
 37             {
 38                 dis[i]=dis[cur]+kcost[cur][i];
 39                 pre[i]=cur;
 40                 if(!vis[i])
 41                 {
 42                     vis[i]=1;
 43                     q.push(i);
 44                 }
 45             }
 46         }
 47     }
 48     return pre[t]!=-1;//pre[t]==-1表示无增广路
 49 }
 50 
 51 void costflow()
 52 {
 53     int minf=inf;
 54     while(spfa())
 55     {
 56         for(int u=t;pre[u] != -1;u=pre[u])
 57         {
 58             minf=min(minf,cap[pre[u]][u]-flow[pre[u]][u]);
 59         }
 60         for(int u=t;pre[u] !=-1 ;u=pre[u])//沿着最小费用路进行增广
 61         {
 62             flow[pre[u]][u]+=minf;
 63             flow[u][pre[u]]-=minf;
 64         }
 65     }
 66 }
 67 
 68 int main()
 69 {
 70     while(scanf("%d%d%d",&n,&m,&k))
 71     {
 72         if(!n && !m && !k) break;
 73         int flag=1;//判断是否无解
 74         memset(supply,0,sizeof(supply));
 75         memset(demand,0,sizeof(demand));
 76         for(int i=1;i<=n;i++)
 77         {
 78             for(int j=1;j<=k;j++)
 79             {
 80                 scanf("%d",&order[i][j]);
 81                 demand[j]+=order[i][j];
 82             }
 83         }
 84         for(int i=1;i<=m;i++)
 85         {
 86             for(int j=1;j<=k;j++)
 87             {
 88                 scanf("%d",&store[i][j]);
 89                 supply[j]+=store[i][j];
 90             }
 91         }
 92         for(int p=1;p<=k;p++)
 93         {
 94             for(int i=1;i<=n;i++)
 95             {
 96                 for(int j=1;j<=m;j++)
 97                 {
 98                     scanf("%d",&cost[p][j][i]);
 99                 }
100             }
101         }
102         for(int i=1;i<=k;i++)
103         {
104             if(demand[i]>supply[i])
105             {
106                 flag=0;
107                 break;
108             }
109         }
110         int flowcost=-1;
111         if(flag)
112         {
113             s=0;
114             t=n+m+1;
115             //按照商品数构图k次
116             //cap,kcost,下标1----m为供应站,m+1--m+n为商店
117             flowcost=0;
118             for(int p=1;p<=k;p++)
119             {
120                 memset(cap,0,sizeof(cap));
121                 memset(kcost,0,sizeof(kcost));
122                 memset(flow,0,sizeof(flow));
123                 for(int i=1;i<=m;i++)//源点到供应站建边
124                     cap[s][i]=store[i][p];
125                 for(int i=1;i<=n;i++)
126                     cap[i+m][t]=order[i][p];
127                 for(int i=1;i<=m;i++)
128                 {
129                     for(int j=1;j<=n;j++)
130                     {
131                         cap[i][j+m]=store[i][p];
132                         kcost[i][j+m]=cost[p][i][j];
133                         kcost[j+m][i]=-cost[p][i][j];//负费用,表示回流费用增加
134                     }
135                 }
136                 costflow();
137                 for(int i=1;i<=m;i++)
138                 {
139                     for(int j=1;j<=n;j++)
140                         flowcost+=kcost[i][j+m]*flow[i][j+m];//单价乘流量
141                 }
142             }
143         }
144         printf("%d\n",flowcost);
145     }
146     return 0;
147 }
原文地址:https://www.cnblogs.com/Missa/p/2802395.html