学了最小费用流的增广路算法后,就用它写了 对于每个物品,分别建图求一次最小费用流,把结果相加就行 少打了一个break,查了1个小时。。。唉 代码: #include<iostream> #include<queue> using namespace std; #define MAX 120 #define inf 99999999 int pre[MAX],c[MAX][MAX],f[MAX][MAX],b[MAX][MAX],cost[MAX][MAX][MAX]; int order[MAX][MAX],store[MAX][MAX],d[MAX],need[MAX],total[MAX]; bool vis[MAX]; int n,m,k,s,t,ans,max_flow,min_cost; void spfa() { int i,j; queue<int>q; memset(vis,0,sizeof(vis)); while(!q.empty()) q.pop(); q.push(s); vis[s]=true; while(!q.empty()) { i=q.front(); q.pop(); vis[i]=false; for(j=0;j<=n+m+1;j++) { if(c[i][j]>f[i][j]&&d[j]>d[i]+b[i][j]) { d[j]=d[i]+b[i][j]; pre[j]=i; if(!vis[j]) { q.push(j); vis[j]=true; } } } } } void mcmf() { int i,minf; while(true) { memset(pre,-1,sizeof(pre)); for(i=0;i<=n+m+1;i++) d[i]=inf; d[s]=0; spfa(); if(pre[t]==-1) break; i=t; minf=inf; while(pre[i]!=-1) { if(c[pre[i]][i]-f[pre[i]][i]<minf) { minf=c[pre[i]][i]-f[pre[i]][i]; } i=pre[i]; } i=t; while(pre[i]!=-1) { f[pre[i]][i]+=minf; f[i][pre[i]]=-f[pre[i]][i]; i=pre[i]; } //ans+=d[t]; //每条边费用不为0的边上的流量不一定为1 } } int main() { int i,j,l,flag; while(scanf("%d %d %d",&n,&m,&k)!=EOF) { if(n==0&&m==0&&k==0) break; memset(need,0,sizeof(need)); memset(total,0,sizeof(total)); ans=0; s=0; t=n+m+1; for(i=1;i<=n;i++) { for(j=1;j<=k;j++) { scanf("%d",&order[i][j]); need[j]+=order[i][j];//j种货物需求量 } } for(i=1;i<=m;i++) { for(j=1;j<=k;j++) { scanf("%d",&store[i][j]); total[j]+=store[i][j];//j种货物供应量 } } for(l=1;l<=k;l++) { for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&cost[l][j][i]); } } flag=1; for(i=1;i<=k;i++) { if(need[i]>total[i]) { printf("-1/n"); flag=0; break;//一开始少了个break,可能一组数据输出多个-1 } } if(flag) { for(l=1;l<=k;l++) { memset(c,0,sizeof(c)); memset(f,0,sizeof(f)); memset(b,0,sizeof(b)); for(i=1;i<=m;i++) c[s][i]=store[i][l];//源点向仓库连边,容量为该仓库第l种货物的储量 for(i=1;i<=n;i++) c[i+m][t]=order[i][l];//每个商店向汇点连边,容量为该商店的需求量 for(i=1;i<=m;i++) { for(j=1;j<=n;j++) { c[i][j+m]=store[i][l];//每个仓库i能为每个商店j提供该仓库中的所有l号货物 b[i][j+m]=cost[l][i][j]; b[j+m][i]=-b[i][j+m];//表示逆流费用与正流相反 } } mcmf(); for(i=1;i<=m;i++) for(j=1;j<=n;j++) ans+=f[i][j+m]*b[i][j+m];//求最小费用 } printf("%d/n",ans); } } //system("pause"); return 0; }