POJ 2516 最小费用流

本文详细介绍了最小费用流算法的实现细节,通过一个具体的例子展示了如何利用该算法解决实际问题。文章首先定义了所需的变量和数据结构,接着逐步解析了算法的流程,包括构建图模型、寻找增广路径以及更新流量等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做的第一个最小费用流问题,第一次忘了费用乘以流量 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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值