POJ-2516-Minimum Cost

来源:互联网 发布:小米服务号是什么软件 编辑:程序博客网 时间:2024/05/21 06:16

POJ-2516-Minimum Cost

http://poj.org/problem?id=2516

N个顾客,M个供应商,K种货物,给出一些供求关系,求满求条件的最小代价

最小费用最大流,对k种货物的每一种求一次最小费用,相加即可

#include<stdio.h>#include<string.h>#include<math.h>#define maxn 300#define INF 0x7fffffffint min(int x,int y){return x<y?x:y;}int map[maxn][maxn],vis[maxn],cap[maxn][maxn],dis[maxn];int que[maxn],pre[maxn];int num,ans;int SPFA() {int i,k;int head,tail;memset(vis,0,sizeof(vis));for(i=0;i<=num;i++)dis[i]=INF;dis[0]=0;vis[0]=1;head=tail=0;que[0]=0;tail++;while(head<tail){       k=que[head];   vis[k]=0;   for(i=0;i<=num;i++)   {   if(cap[k][i]&&dis[i]>dis[k]+map[k][i])   {   dis[i]=dis[k]+map[k][i];   pre[i]=k;   if(!vis[i])   {   vis[i]=1;   que[tail++]=i;   }   }   }   head++;}if(dis[num]<INF)return 1;return 0;}void end(){int i,sum=INF;for(i=num;i!=0;i=pre[i])sum=min(sum,cap[pre[i]][i]);for(i=num;i!=0;i=pre[i]){cap[pre[i]][i]-=sum;cap[i][pre[i]]+=sum;ans+=map[pre[i]][i]*sum;}}int main(){int N,M,K,i,j,k;int need[maxn][maxn],needk[maxn];int have[maxn][maxn],havek[maxn];int flag;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];}flag=1;for(i=1;i<=K;i++)if(needk[i]>havek[i]){flag=0;break;}ans=0;num=N+M+1;for(k=1;k<=K;k++)   //处理每一种货物{memset(cap,0,sizeof(cap)); memset(map,0,sizeof(map));for(i=1;i<=N;i++)for(j=1;j<=M;j++){scanf("%d",&map[j][M+i]);map[M+i][j]=-map[j][M+i];cap[j][M+i]=have[j][k];cap[M+i][j]=0;}    if(!flag)continue;for(i=1;i<=M;i++)  //源点向供应商建边{cap[0][i]=have[i][k];map[0][i]=map[i][0]=0;}for(i=1;i<=N;i++) //顾客向汇点建边{cap[M+i][num]=need[i][k];map[M+i][num]=map[num][M+i]=0;}while(SPFA())end();}if(flag)printf("%d\n",ans);else    printf("-1\n");}return 0;}



原创粉丝点击