题意大意:有N个客户,M个仓库,和K种货物。已知每个客户需要每种货物的数量,每个仓库存储每种货物的数量,每个仓库运输各种货物去各个客户的单位费用。判断所有的仓库能否满足所有客户的需求,如果可以,求出最少的运输总费用。
思路:最小费用最大流,这道题我是直接用了模板。
#include<iostream> using namespace std; #include <memory.h> const int inf = 99999999; const int Max = 110; int get_min( int a, int b ) { if (a>b) return b; return a; } int n, ans; int cap[Max][Max], pre[Max]; int cost[Max][Max], dis[Max]; int que[Max]; bool vis[Max]; bool spfa(){ // 源点为0,汇点为n。 int u,i, head = 0, tail = 1; for(i = 0; i <= n; i ++){ dis[i] = inf; vis[i] = false; } dis[0] = 0; que[0] = 0; while(tail != head){ // 循环队列。 u = que[head]; vis[u] = true; for(i = 0; i <= n; i ++) if(cap[u][i] && dis[i] > dis[u] + cost[u][i]){ // 存在路径,且权值变小。 dis[i] = dis[u] + cost[u][i]; pre[i] = u; if(!vis[i]){ vis[i] = true; que[tail ++] = i; if(tail == Max) tail = 0; } } vis[u] = false; head ++; if(head == Max) head = 0; } if(dis[n] == inf) return false; return true; } void end(){ int i, sum = inf; for(i = n; i != 0; i = pre[i]) sum = get_min(sum, cap[pre[i]][i]); for(i = n; i != 0; i = pre[i]){ cap[pre[i]][i] -= sum; cap[i][pre[i]] += sum; ans += cost[pre[i]][i] * sum; // cost[][]记录的为单位流量费用,必须得乘以流量。 } } int main() { int N,M,K,i,j,k; int need[Max][Max],NeedK[Max]; int have[Max][Max],HaveK[Max]; while (scanf("%d%d%d",&N,&M,&K)&&N) { memset(NeedK,0,sizeof(NeedK)); for (i=1;i<=N;i++) { for (j=1;j<=K;j++) { scanf("%d",&need[i][j]); NeedK[j]+=need[i][j]; } } memset(HaveK,0,sizeof(HaveK)); for (i=1;i<=M;i++) { for (j=1;j<=K;j++) { scanf("%d",&have[i][j]); HaveK[j]+=have[i][j]; } } bool flag=true; for (i=1;i<=K;i++) { if (NeedK[i]>HaveK[i]) { flag=false; break; } } ans=0; n=N+M+1; for (k=1;k<=K;k++) { memset(cap,0,sizeof(cap)); for (i=1;i<=N;i++) { for (j=1;j<=M;j++) { scanf("%d",&cost[j][M+i]); cost[M+i][j]=-cost[j][M+i]; cap[j][M+i]=inf; } } if (!flag) continue; for (i=1;i<=M;i++) { cap[0][i] = have[i][k]; cost[0][i] = cost[i][0] = 0; } for(i = 1; i <= N; i ++){ cap[M+i][n] = need[i][k]; cost[M+i][n] = cost[n][M+i] = 0; } while (spfa()) end(); } if (flag) cout << ans << endl; else cout << -1 << endl; } return 0; }