【Luogu】P3381最小费用最大流模板(SPFA找增广路)
哈 学会最小费用最大流啦
思路是这样。
首先我们有一个贪心策略。如果我们每次找到单位费用和最短的一条增广路,那么显然我们可以把这条路添加到已有的流量里去——不管这条路的流量是多大,反正它能扩大现有流量,而且目前为止它是可以扩大流量的所有路径中单位花费最少的。
然后我们就把这条路填上。想想看当我们找不到这样一条路的时候会发生什么?
那就是没有增广路了。恭喜我们获得最小费用最大流。这是为什么呢?
首先没有任何一条增广路的时候我们肯定获得最大流没错
然后我们回顾我们扩展的方式。每次我们都选择了一条单位费用和最短的路径,也就是说,我们总是先把便宜的路尽可能利用完了,才去利用那些贵的。鉴于此,我们总是已经把更便宜的填满了,整张图上没有更便宜的路了,才去尝试探索更贵的。
那么这就是最小费用qwq
那这个思路怎么实现呢?
我们可以把边的长度设为单位费用,然后对每个点SPFA。这样SPFA算出来的每个点的距离就是可走增广路中从起点到这个点最少的单位费用和。
然后SPFA过程中顺便求路径上的流量。顺便记录用了哪些边 最后暴力回跳修改边的信息。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define maxn 5050
#define maxm 10050
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} inline int count(int i){ return i&?i+:i-; } struct Edge{
int from,to,next,val,dis,flow;
}edge[maxm*];
int head[maxn],num;
inline void addedge(int from,int to,int val,int dis){
edge[++num]=(Edge){from,to,head[from],val,dis,};
head[from]=num;
}
inline void add(int from,int to,int val,int dis){
addedge(from,to,val,dis);
addedge(to,from,,-dis);
} bool vis[maxn];
int pre[maxn];
int cost[maxn];
int dst[maxn]; struct Answer{
bool flag;long long flow;long long cost;
}; Answer spfa(int Start,int End){
Answer ans=(Answer){,,};
memset(dst,/,sizeof(dst)); dst[Start]=; cost[Start]=0x7fffffff;
queue<int> f;
f.push(Start);
while(!f.empty()){
int from=f.front(); f.pop();
vis[from]=;
for(int i=head[from];i;i=edge[i].next){
int to=edge[i].to;
if(edge[i].val<=edge[i].flow||dst[to]<=dst[from]+edge[i].dis) continue;
dst[to]=dst[from]+edge[i].dis;
pre[to]=i;
cost[to]=min(cost[from],edge[i].val-edge[i].flow);
if(!vis[to]){
vis[to]=;
f.push(to);
}
}
}
if(dst[End]==dst[]) return ans;
ans.flag=;ans.flow+=cost[End]; ans.cost+=(long long)dst[End]*cost[End];
int now=End;
while(now!=Start){
int ret=pre[now];
edge[ret].flow+=cost[End];
edge[count(ret)].flow-=cost[End];
now=edge[ret].from;
}
return ans;
} long long Flow,Cost; int main(){
int n=read(),m=read(),Start=read(),End=read();
for(int i=;i<=m;++i){
int from=read(),to=read(),val=read(),dis=read();
add(from,to,val,dis);
}
while(){
Answer ans=spfa(Start,End);
if(!ans.flag) break;
if(!ans.flow) break;
Flow+=ans.flow;
Cost+=ans.cost;
}
printf("%lld %lld",Flow,Cost);
return ;
}
【Luogu】P3381最小费用最大流模板(SPFA找增广路)的更多相关文章
- 洛谷P3381 最小费用最大流模板
https://www.luogu.org/problem/P3381 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用 ...
- luogu 3376 最小费用最大流 模板
类似EK算法,只是将bfs改成spfa,求最小花费. 为什么可以呢,加入1-3-7是一条路,求出一个流量为40,那么40*f[1]+40*f[2]+40*f[3],f[1]是第一条路的单位费用,f[2 ...
- 【luogu P3381 最小费用最大流】 模板
题目链接:https://www.luogu.org/problemnew/show/P3381 把bfs变成spfa #include <queue> #include <cstd ...
- HDU3376 最小费用最大流 模板2
Matrix Again Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)To ...
- 最大流 && 最小费用最大流模板
模板从 这里 搬运,链接博客还有很多网络流题集题解参考. 最大流模板 ( 可处理重边 ) ; const int INF = 0x3f3f3f3f; struct Edge { int from ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- 【网络流#2】hdu 1533 - 最小费用最大流模板题
最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...
- poj 2195 最小费用最大流模板
/*Source Code Problem: 2195 User: HEU_daoguang Memory: 1172K Time: 94MS Language: G++ Result: Accept ...
- POJ2135 最小费用最大流模板题
练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include ...
随机推荐
- vue从入门到开发--1-安装脚手架
一: 1.在文件目录下打开命令窗口(按住shift+右键[在此处打开命令窗口]或者直接ctrl+R打开命令窗口,利用cd选择到自己的文件目录) 2.$ npm install --global vue ...
- 解决 Cocos2d-x 3.2 error C1041: 无法打开程序数据库vc120.pdb
单个项目解决方案 解决方案是为项目添加 /FS (Force Synchronous PDB Writes) 编译选项,具体位置在: 一劳永逸的解决方案 直接修改cocos的项目模板templates ...
- iOS 锁的常用方法
锁的用法在iOS中有几种方法来解决多线程访问同一个内存地址的互斥同步问题: 方法一,@synchronized(id anObject),(最简单的方法)会自动对参数对象加锁,保证临界区内的代码线程安 ...
- 记AccessibilityService使用(转)
转自 :http://www.jianshu.com/p/ba298b8d5a6e 一.AccessibilityService的使用 首先先写一个类去继承AccessibilityService p ...
- Spark-水库抽样-根据抽样率确定每个分区的样本大小
/* * 输入:采样率,待采样的RDD * 输出:每个分区的样本大小(记录数) * 由采样率确定,每个分区的样本大小 */ def findNumPerPartition[T: ClassTag, U ...
- python GIL锁问题
一.GIL是什么 官方解释: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple na ...
- 多数据源连接Oracle报错,linux熵池耗尽问题
最近碰到了个很有意思的问题,springboot加载多数据源,遇到了在启动时数据库连接报错的问题. 报错信息: The error occurred while executing a query 然 ...
- C# 使用Epplus导出Excel [3]:合并列连续相同数据
C# 使用Epplus导出Excel [1]:导出固定列数据 C# 使用Epplus导出Excel [2]:导出动态列数据 C# 使用Epplus导出Excel [3]:合并列连续相同数据 C# 使用 ...
- Python从文件中读取数据
一.读取整个文件内容 在读取文件之前,我们先创建一个文本文件resource.txt作为源文件. resource.txt my name is joker, I am 18 years old, H ...
- linux时钟概念CST与UTC、以及NTP简单设置
1.世界协调时间(Universal Time Coordinated,UTC): GPS 系统中有两种时间区分,一为UTC,另一为LT(地方时)两者的区别为时区不同,UTC就是0时区的时间,地方时为 ...