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 }

 

你可能感兴趣的:(poj)