最小费用最大流,一般解法如下:

在流量基础上,每条边还有权费用,即单位流量下的所需费用。在最大流量下,求最小费用。解法:在最大流算法基础上,每次按可行流增广改为每次用spfa按最小费用(用单位费用)增广,每次按每条边一单位费用求到达终点的最小费用(最短路),那么每次找到“最短路”(只是一条路,不是多条(dinic每次可以增广多条)),之后按这条路最大

可能流量增广(取这条路上残量最小的),直到无法增广为止。(实现细节点代码备注)。

该题题意:m个供应地向n个商店供应k种物品,对于每种物品,供应地有相应库存量,商店有相应需求量,从供应地j到商店i每单位物品需要路费cost,求满足所有商店的最小费用。

思路:对于每种商品,若供不应求,则无解。反之:对于每种物品,建立源点0,汇点 n+m+1,。从 0到供应地有边,流量为供应地库存,费用为0,从商店到汇点,流量为该商店需求量,费用为0,从供应地到商店,费用为路费,流量为inf,问题转化为最小费用最大流(满足所有商店,刚刚最大,满流)。

#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int n,m,k;
int shop[60][55];int sup[55][55]; //第i个shop/sup 的第j种商品的供求量
int fire[55][55][55]; //第i种商品从第k个供应商到第j个商店的路费.
int e[8000][4];int head[105];int nume=0;
const int inf=0x3f3f3f3f;
void inline adde(int i,int j,int f,int cost) //addedge,注意反向边可以费用取反!因为“后悔”时候可以减去费用。
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=f;e[nume++][3]=cost;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
e[nume][2]=0;e[nume++][3]=-cost;
}
void build(int ii) //建图
{
for(int i=1+m;i<=n+m;i++)
adde(i,n+m+1,shop[i-m][ii],0);
for(int i=1;i<=m;i++)
adde(0,i,sup[i][ii],0);
for(int i=1;i<=m;i++)
for(int j=m+1;j<=m+n;j++)
adde(i,j,inf,fire[ii][j-m][i]); }
int inq[105];int d[105]; //spfa
bool spfa(int & sum) //每次求费用
{
int pre[105];
int minf=inf;
int pr[105];
for(int i=0;i<n+m+2;i++)
{
inq[i]=0;
d[i]=inf;
}
pre[0]=-1 ; pr[0]=-1; //路径中,分别记录到点i的边,和i之前的点。(这题如果用矩阵建图要方便)
queue<int>q;
q.push(0);inq[0]=1;d[0]=0;
while(!q.empty())
{
int cur=q.front();
q.pop();
inq[cur]=0;
for(int i=head[cur];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(e[i][2]>0&&e[i][3]+d[cur]<d[v])
{
d[v]=e[i][3]+d[cur];
pr[v]=cur; //记录增广路
pre[v]=i;
if(!inq[v])
{
q.push(v);
inq[v]=1;
}
}
}
}
if(d[n+m+1]==inf)return 0; //无法增广
int cur=n+m+1; //目的点
while(cur!=0) //取路径上最小残流量边作为流量增广
{
minf=e[pre[cur]][2]<minf?e[pre[cur]][2]:minf;
cur=pr[cur];
}
cur=n+m+1;
while(cur!=0) //增广,改流量
{
e[pre[cur]][2]-=minf;
e[pre[cur]^1][2]+=minf;
cur=pr[cur];
}
sum+=d[n+m+1]*minf; //费用为单位费用(该路径下每条边单位流量之和)*流量
return 1;
}
int mincost()
{
int sum=0;
while(spfa(sum)); //无法增广为止
return sum;
}
int sumshop[55];int sumsup[55];
int main()
{
while(scanf("%d%d%d",&n,&m,&k)&&(n||m||k))
{
for(int i=1;i<=k;i++)
{
sumsup[i]=sumshop[i]=0;
} for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
{
scanf("%d",&shop[i][j]);
sumshop[j]+=shop[i][j];
}
for(int i=1;i<=m;i++)
for(int j=1;j<=k;j++)
{
scanf("%d",&sup[i][j]);
sumsup[j]+=sup[i][j];
}
for(int i=1;i<=k;i++)
for(int ii=1;ii<=n;ii++)
for(int iii=1;iii<=m;iii++)
scanf("%d",&fire[i][ii][iii]);
int flag=1;
for(int i=1;i<=k;i++)
{
if(sumsup[i]<sumshop[i]) //供不应求
{
cout<<-1<<endl;
flag=0;
break;
}
}
if(flag==0)continue;
int sumcost=0;
for(int i=1;i<=k;i++) //每种物品最小费用之和
{
for(int ii=0;ii<n+m+5;ii++)
head[ii]=-1;
nume=0;
build(i);
sumcost+=mincost();
}
cout<<sumcost<<endl;
}
}

最小费用最大流粗解 poj2516的更多相关文章

  1. hdu 2686 Matrix 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 Yifenfei very like play a number game in the n*n ...

  2. hdu 1533 Going Home 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533 On a grid map there are n little men and n house ...

  3. POJ2516 Minimum Cost(最小费用最大流)

    一开始我把每个店主都拆成k个点,然后建图..然后TLE.. 看题解= =哦,愚钝了,k个商品是独立的,可以分别跑k次最小费用最大流,结果就是k次总和.. #include<cstdio> ...

  4. POJ2516 Minimum Cost【最小费用最大流】

    题意: 有N个客户,M个仓库,和K种货物.已知每个客户需要每种货物的数量,每个仓库存储每种货物的数量,每个仓库运输各种货物去各个客户的单位费用.判断所有的仓库能否满足所有客户的需求,如果可以,求出最少 ...

  5. HDU5900 QSC and Master(区间DP + 最小费用最大流)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...

  6. UVa12092 Paint the Roads(最小费用最大流)

    题目大概说一个n个点m条带权有向边的图,要给边染色,染色的边形成若干个回路且每个点都恰好属于其中k个回路.问最少要染多少边权和的路. 一个回路里面各个点的入度=出度=1,那么可以猜想知道各个点如果都恰 ...

  7. HIT2739 The Chinese Postman Problem(最小费用最大流)

    题目大概说给一张有向图,要从0点出发返回0点且每条边至少都要走过一次,求走的最短路程. 经典的CPP问题,解法就是加边构造出欧拉回路,一个有向图存在欧拉回路的充分必要条件是基图连通且所有点入度等于出度 ...

  8. 网络流之最小费用最大流 P1251 餐巾计划问题

    题目描述 一个餐厅在相继的 NN 天里,每天需用的餐巾数不尽相同.假设第 ii 天需要 r_iri​块餐巾( i=1,2,...,N).餐厅可以购买新的餐巾,每块餐巾的费用为 pp 分;或者把旧餐巾送 ...

  9. TZOJ 1513 Farm Tour(最小费用最大流)

    描述 When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 &l ...

随机推荐

  1. Java的jdbc调用SQL Server存储过程Bug201906131119

    SQL Server数据库存储过程,一个查询使用动态sql,另一个不使用动态sql,这种情况,jdbc可能获取不到实际查询数据,虽然数据库中执行没问题. 解决方法,都使用静态sql,或都使用动态sql ...

  2. IjkPlayer播放器秒开优化以及常用Option设置

    https://blog.csdn.net/shareus/article/details/78585260 ijkplayer点播和直播视频 问题 解决及优化  https://blog.csdn. ...

  3. web框架 http协议

    http 协议是超文本传输协议,位于osi七层的应用层,协议规定的就是请求与响应双方的一个消息格式,请求(请求行,请求头,空行,请求数据,请求行--请求方式URL协议版本\r\n请求头--user-a ...

  4. Java InputStream、String、File相互转化

    String --> InputStreamByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes()); Inp ...

  5. html制作简单框架网页 实现自己的音乐驿站 操作步骤及源文件下载 (播放功能限mp3文件)

    使用HTML语言来设计制作 Hyper Text Markup Language 超文本标记语言 这门语言的特点就是标记,就是把所有的命令单词用<>标记起来,就可以发挥作用 还有一个特点, ...

  6. C语言数组_04

    概念:数组是在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来的一种形式.这些按序排列的同类数据元素的集合称为数组.在C语言中,数组属于构造数据类型.一个数组可以分解为多个数组 ...

  7. MySQL中常见的锁

    一.按读写方式分类 1.读锁又称共享锁,读锁是共享的,读锁之间是互不阻塞. 2.写锁又称排他锁,写锁是排他的,写锁会阻塞其他读锁和写锁 二.按锁的粒度分类 1.表锁是MySQL中最基本的锁策略,该锁的 ...

  8. webpack-dev-server proxy代理

    一个最简单的代理例子:index.html中有如下代码 fetch('/api/pub/article/list?pageSize=2').then((data)=>{ return data. ...

  9. 关于priority_queue的一些说明

    参考GGBeng 相关定义 优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素.但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大 ...

  10. BZOJ 4504: K个串

    题目大意: 求一个序列的第k大的子串和. 题解: 对于一个右端点找最优的左端点,扔进堆里. 每次取堆顶,将这个右端点可以选择的左端点的区间分成两段,扔进堆里,重复k次. 现在需要对于一个固定的右端点, ...