看了下SPFA题解,一个一个太麻烦了,另一个写的很不清楚,而且注释都变成了"????"不知道怎么过的,于是自己来一发SPFA算法。

Part 1.题意

M 个仓库,卖给 N 个商店,两个问,第一问求运价最小值,第二问最大值。

显然是一个最小费用最大流(MCMF)。

Part 2.思路

1.连让每个仓库连接一个超级源点 SS ,费用(dis)为0,流量为仓库的流量,表示每个仓库最多可以运出多少货物。

2.让每一个仓库连接每一家商店,边权为 cost[i][j] ,其中,i为仓库编号,j为商店编号编号,流量为 need[j] ,其实流量可以取得范围是  [need[j]...INF] ,另外如果出现 need[j] <这个仓库货物量的情况也可以不怕(这时候取值的下限变成 min(hw[i],need[j]) ) hw指的是这家仓库的货物,还有注意编号的范围(我默认超级源点是 00 ,仓库是 1……n ,商店是 n+1……n+m ,超级汇点是 10000)

3.让每一家商店连接超级汇点 TT

图像帮助理解: 

Part 3.代码

现在代码就好办了 注释给的很清楚

 #include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm> #define I_copy_this_answer return 0; using namespace std; int n,m,head[],size=;
int mmx=,mincost,maxwater;
int flow[];
int need[],cost[][];
int pre[],las[],dis[],vis[],hw[]; struct edge{
int next,to,dis,flow;
}e[]; void addedge(int next,int to,int dis,int flow)
{
e[++size].to=to;
e[size].dis=dis;
e[size].flow=flow;
e[size].next=head[next];
head[next]=size;
} int spfa(int s)
{
memset(flow,0x3f,sizeof(flow));
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
queue <int> q;
q.push(s);
dis[s]=;
vis[s]=;
pre[mmx]=-; //(其实只要不是与p直接连的点(n+1......n+m)就可以了
while(!q.empty())
{
int t=q.front();
q.pop();
vis[t]=;
int i,j,k,l;
for(i=head[t];i;i=e[i].next)
{
j=e[i].to;
k=e[i].dis;
l=e[i].flow;
if(dis[t]+k<dis[j]&&l>) //没有流量的话这条路就增广不了,最短距离是建立在增广路存在的基础上的
{
dis[j]=dis[t]+k;
las[j]=i; //las指的是这个点(j)与上个点(t)相连的边的编号
pre[j]=t; //pre指的是这条路径上这个点(j)的上一个点
flow[j]=min(flow[t],l); //把当前边流量与上个点的流量对比,解决出现仓库货物比需要的少的情况
if(!vis[j])
{
q.push(j);
vis[j]=;
}
}
}
}
return pre[mmx]!=-; //如果不是这个值就说明这个点被刷新,增广成功
} void mcmf()
{
while(spfa())
{
mincost+=dis[mmx]*flow[mmx]; //从源点出发到汇点的单位费用再乘以单位,由于每次只增广一条路,而且仓库和商店是直接连接的,可以这样写
int t=mmx;
while(t!=)
{
e[las[t]].flow-=flow[mmx]; //回溯,修改每条边的流量,因为该算法中途找到的增广路不是最后的增广路,所以这个要等到最后来改变
e[las[t]^].flow+=flow[mmx];
t=pre[t];
}
}
} void build_edge(int t)
{
int i,j;
for(i=;i<=m;i++)
{
addedge(,i,,hw[i]);
addedge(i,,,);
}
for(i=;i<=m;i++)
for(j=;j<=n;j++)
{
addedge(i,j+m,cost[i][j]*t,need[j]);
addedge(j+m,i,-cost[i][j]*t,);
}
for(i=;i<=n;i++)
{
addedge(i+m,mmx,,need[i]);
addedge(mmx,i+m,,);
}
} int main()
{
int i,j;
scanf("%d %d",&m,&n);
for(i=;i<=m;i++)
{
int t1;
scanf("%d",&hw[i]);
}
for(i=;i<=n;i++)
scanf("%d",&need[i]);
for(i=;i<=m;i++)
for(j=;j<=n;j++)
scanf("%d",&cost[i][j]); //读入,与上面的cost,need,hw如果不明白可以对照输入格式看代表什么意思
build_edge(); //建立边权为正的边,跑最小费用最大流
mcmf();//最小费用最大流(Min Cost Max Flow )的缩写
printf("%d",mincost);
maxwater=;
mincost=;
size=;
memset(head,,sizeof(head));
build_edge(-);
mcmf();
printf("\n%d",-mincost);
I_copy_this_answer
}

洛谷P4015 运输问题 网络流24题的更多相关文章

  1. 洛谷P4011 【网络流24题】 孤岛营救问题 (BFS+状压)

    一道妙题啊......(不知道为什么这道题的标签是网络流,不需要用网络流啊) 如果没有门和钥匙,连边(边权为1)求最短路就行了. 但是有这两个因素的限制,我们采用分层建图的思想,一共2p层,每层对应持 ...

  2. 洛谷P4014分配问题——网络流24题

    题目:https://www.luogu.org/problemnew/show/P4014 最大/小费用最大流裸题. 代码如下: #include<iostream> #include& ...

  3. 洛谷P4015 运输问题(费用流)

    传送门 源点向仓库连费用$0$,流量为储量的边,商店向汇点连费用$0$,流量为需求的边,然后仓库向商店连流量$inf$,费用对应的边,跑个费用流即可 //minamoto #include<io ...

  4. [洛谷P4015]运输问题

    题目大意:有m个仓库和n个商店.第i个仓库有 $a_{i}$ 货物,第j个商店需要$b_{j}$个货物.从第i个仓库运送每单位货物到第j个商店的费用为$c_{i,j}$​​.求出最小费用和最大费用 题 ...

  5. 洛谷 P4015 运输问题 【最小费用最大流+最大费用最大流】

    s向仓库i连ins(s,i,a[i],0),商店向t连ins(i+m,t,b[i],0),商店和仓库之间连ins(i,j+m,inf,c[i][j]).建两次图分别跑最小费用最大流和最大费用最大流即可 ...

  6. 洛谷P4015 运输问题(费用流)

    题目描述 WW 公司有 mm 个仓库和 nn 个零售商店.第 ii 个仓库有 a_iai​ 个单位的货物:第 jj 个零售商店需要 b_jbj​ 个单位的货物. 货物供需平衡,即\sum\limits ...

  7. 洛谷P4009汽车加油行驶问题——网络流24题(最短路)

    题目:https://www.luogu.org/problemnew/show/P4009 网络流24题中不是网络流的最短路题: 把每个点拆成各个油量上的点,根据要求连边即可: 注意:点数最大为10 ...

  8. [网络流24题] 洛谷P2761 软件补丁问题

    题意:某公司发现其研制的一个软件中有 n个错误,随即为该软件发放了一批共 m 个补丁程序.对于每一个补丁 i ,都有 2 个与之相应的错误集合 B1(i)和 B2(i),使得仅当软件包含 B1(i)中 ...

  9. [洛谷P3254] [网络流24题] 圆桌游戏

    Description 假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为ri (i =1,2,--,m). 会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,--,n) ...

随机推荐

  1. python文件操作【目录大全】

    总是记不住API.昨晚写的时候用到了这些,但是没记住,于是就索性整理一下吧: python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Pyth ...

  2. ubuntu命令查看英伟达显卡型号

    在终端输入如下命令:nvidia-smi

  3. Distilling the Knowledge in a Neural Network

    url: https://arxiv.org/abs/1503.02531 year: NIPS 2014   简介 将大模型的泛化能力转移到小模型的一种显而易见的方法是使用由大模型产生的类概率作 ...

  4. Rust对协程的思考

    最近和同事聊起来,觉得lua缺乏编译型语言的类型校验功能,还有变量拼写检查之类的,导致线上总是有低级错误出现.比如最近有一个是变量名拼写少了一个字母,导致某功能没开启:还有一个是变量传参时,之前测试多 ...

  5. 转载:点云上实时三维目标检测的欧拉区域方案 ----Complex-YOLO

    感觉是机器翻译,好多地方不通顺,凑合看看 原文名称:Complex-YOLO: An Euler-Region-Proposal for  Real-time 3D Object Detection ...

  6. C#函数的参数传递2(ref\out)

    using System; namespace class1 { class program { static void Main(string[] args) { Console.Write(&qu ...

  7. Python 自定义元类的两种写法

    有关元类是什么大家自己搜索了解,我这里写一下实现元类的两种写法 # 自定义元类 #继承type class LowercaseMeta(type): ''' 修改类的属性名称为小写的元类 ''' # ...

  8. LinuxShell脚本——认识Shell脚本

    LinuxShell脚本——认识Shell脚本 摘要:本文主要介绍了Shell脚本的一些基本知识. 什么是Shell脚本 shell脚本是利用shell的功能所写的一个程序,这个程序是使用纯文本文件, ...

  9. 计科菜鸟玩生信(一)——Windows10下用docker安装GATK

    1.官网下载GATK. (学校网速实在是太慢了,下载几个小时到自闭) 下载地址:https://software.broadinstitute.org/gatk/download/ 下载完成后文件夹中 ...

  10. Javase之内部类概述

    内部类概述 把类定义在其他类的内部就称为内部类 class A{ class B{ } } B就称为内部类,A称为外部类. 内部类的访问特点 内部类直接访问外部类成员,包括私有. 外部类要访问内部类要 ...