做的第一個最小費用流問題,第一次忘了費用乘以流量 WA了一次,每次輸入一個矩陣都運行一次最小費用流即可。
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
#define INF 0x1f1f1f1f
#define MIN(a,b) ((a)<(b)?(a):(b))
int store[60][60];//儲量
int book[60][60];//訂購量
int cost[200][200]; //花費
int flow[200][200]; //流量
int cap[200][200]; //容量
#define SIZE 200 //圖大小
void cost_flow(int& max_flow,int& min_cost,int st,int ed,int src,int tar)
{
int pre[SIZE];
int dis[SIZE];
bool fl[SIZE];
while(1)
{
memset(pre,-1,sizeof(pre));
memset(dis,0x1f,sizeof(dis));
memset(fl,0,sizeof(fl));
queue<int>q;
q.push(src);
dis[src]=0;
//使用Bellman_ford尋找增廣路及最短距離
while(!q.empty())
{
int u=q.front();
q.pop();
fl[u]=0;
for(int i=st;i<=ed;i++)
{
if(cap[u][i]>flow[u][i]&&dis[u]+cost[u][i]<dis[i])
{
dis[i]=dis[u]+cost[u][i];
pre[i]=u;
if(!fl[i])
{
fl[i]=1;
q.push(i);
}
}
}
}
//
if(pre[tar]==-1)break;
int min=INF;
for(int i=tar;pre[i]!=-1;i=pre[i])
{
min=MIN(min,cap[pre[i]][i]-flow[pre[i]][i]);
}
for(int i=tar;pre[i]!=-1;i=pre[i])
{
flow[pre[i]][i]+=min;
flow[i][pre[i]]-=min;
}
max_flow+=min;
min_cost+=min*dis[tar];
}
}
int main()
{
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k),n||k||m)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<k;j++)
{
scanf("%d",&book[i][j]);
}
}
for(int i=0;i<m;i++)
{
for(int j=0;j<k;j++)
{
scanf("%d",&store[i][j]);
}
}
int res=0;
for(int p=0;p<k;p++)
{
memset(cost,0,sizeof(cost));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&cost[j][i+m]);
cost[i+m][j]=-cost[j][i+m];
}
}
memset(cap,0,sizeof(cap));
memset(flow,0,sizeof(flow));
for(int i=1;i<=m;i++)
{
cap[0][i]=store[i-1][p];
}
for(int i=1;i<=n;i++)
{
cap[m+i][m+n+1]=book[i-1][p];
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cap[i][m+j]=store[i-1][p];
}
}
int flow=0;
int cos=0;
int cnt=0;
for(int i=0;i<n;i++)
{
cnt+=book[i][p];
}
cost_flow(flow,cos,0,m+n+1,0,m+n+1);
if(flow!=cnt)
{
res=-1;
}
else if(res!=-1)
{
res+=cos;
}
}
printf("%d\n",res);
}
return 0;
}