标签:
Time Limit: 4000MS | Memory Limit: 65536K | |
Description
Input
Output
Sample Input
1 3 3 1 1 1 0 1 1 1 2 2 1 0 1 1 2 3 1 1 1 2 1 1 1 1 1 3 2 20 0 0 0
Sample Output
4
-1
题意:有k种物品,m个供应商,n个收购商。每个供应商和收购商都需要一些种类的物品若干。每个供应商与每个收购商之间的对于不同物品的运费是不同的。求满足收购商要求的情况下的最小运费。
分析:最小费用最大流,最大流的前提下求最小费用。这题我们可以把k种物品分开计算,每次对一种物品进行最小费用最大流计算。如果不分开算会超时。对于每种物品,从源到供应商连接,容量为供应商的储存量,费用为0。采购商到汇连边,容量为需求量,费用为0。供应商到采购商连边,容量为无穷,费用为对应的运费。
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; //************************************************************ //最小费用最大流算法 //SPFA求最短路 //邻接矩阵形式 //初始化:cap:容量,没有边为0 //cost:耗费,对称形式,没有边的也为0 //c是最小费用 //f是最大流 //******************************************************* const int MAXN=500; const int INF=0x3fffffff; int cap[MAXN][MAXN];//容量,没有边为0 int flow[MAXN][MAXN]; //耗费矩阵是对称的,有i到j的费用,则j到i的费用为其相反数 int cost[MAXN][MAXN]; int n;//顶点数目0~n-1 int f;//最大流 int c;//最小费用 int st,ed;//源点和汇点 bool vis[MAXN];//在队列标志 int que[MAXN]; int pre[MAXN]; int dis[MAXN];//s-t路径最小耗费 bool SPFA() { int front=0,rear=0; for(int u=0;u<=n;u++) { if(u==st) { que[rear++]=u; dis[u]=0; vis[u]=true; } else { dis[u]=INF; vis[u]=false; } } while(front!=rear) { int u=que[front++]; vis[u]=false; if(front>=MAXN)front=0; for(int v=0;v<=n;v++) { if(cap[u][v]>flow[u][v]&&dis[v]>dis[u]+cost[u][v]) { dis[v]=dis[u]+cost[u][v]; pre[v]=u; if(!vis[v]) { vis[v]=true; que[rear++]=v; if(rear>=MAXN)rear=0; } } } } if(dis[ed]>=INF)return false; return true; } void minCostMaxflow() { memset(flow,0,sizeof(flow)); c=f=0; while(SPFA()) { int Min=INF; for(int u=ed;u!=st;u=pre[u]) Min=min(Min,cap[pre[u]][u]-flow[pre[u]][u]); for(int u=ed;u!=st;u=pre[u]) { flow[pre[u]][u]+=Min; flow[u][pre[u]]-=Min; } c+=dis[ed]*Min; f+=Min; } } //************************************************************ int order[MAXN][MAXN]; int supply[MAXN][MAXN]; int total[MAXN]; int main() { int N,M,K; while(scanf("%d%d%d",&N,&M,&K)==3){ if(N==0&&M==0&&K==0) break; st=0,ed=n=N+M+1; memset(cap,0,sizeof(cap)); memset(cost,0,sizeof(cost)); for(int i=1;i<=N;i++) for(int j=1;j<=K;j++) scanf("%d",&order[i][j]); for(int i=1;i<=M;i++) for(int j=1;j<=K;j++) scanf("%d",&supply[i][j]); for(int i=1;i<=K;i++){ total[i]=0; for(int j=1;j<=N;j++) total[i]+=order[j][i]; } for(int i=1;i<=M;i++) for(int j=M+1;j<=M+N;j++) cap[i][j]=INF; int ans=0; bool flag=true; for(int i=1;i<=K;i++){ for(int j=M+1;j<=M+N;j++){ for(int k=1;k<=M;k++){ scanf("%d",&cost[k][j]); cost[j][k]=-cost[k][j]; } } if(!flag) continue; for(int j=1;j<=M;j++) cap[st][j]=supply[j][i]; for(int j=1;j<=N;j++) cap[j+M][ed]=order[j][i]; minCostMaxflow(); if(f<total[i]) flag=false; else ans+=c; } if(!flag) printf("-1\n"); else printf("%d\n",ans); } return 0; }
POJ 2516 Minimum Cost (最小费用最大流)
标签:
原文地址:http://www.cnblogs.com/wangdongkai/p/5620695.html