【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 ...
随机推荐
- 【转】Create Hello-JNI with Android Studio
[转]Create Hello-JNI with Android Studio From:https://codelabs.developers.google.com/codelabs/android ...
- Linux基础知识介绍
1.Linux知识说明1)文件位置 1)/etc/inittab2)模式介绍 0:挂起模式-不推荐 1:单用户模式-只有管理员可以进入该模式,可以修改root密码,处理有登录权限而没有修改文件的权限问 ...
- mongodb主从配置信息查看与确认
在local库中不仅有主从日志 oplog集合,还有一个集合用于记录主从配置信息 system.replset: > use local > show collections > d ...
- POJ 2831 Can We Build This One?
Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 1728 Accepted: 643 Case Time Limit: 2 ...
- HtmlUnit爬取Ajax动态生成的网页以及自动调用页面javascript函数
HtmlUnit官网的介绍: HtmlUnit是一款基于Java的没有图形界面的浏览器程序.它模仿HTML document并且提供API让开发人员像是在一个正常的浏览器上操作一样,获取网页内容,填充 ...
- chosen选择框加载数据
1.单选$(select).val($("#id").val());$(select).trigger("chosen:updated"); 2.多选 func ...
- CF-1096C Polygon for the Angle
CF-1096C Polygon for the Angle https://codeforces.com/contest/1096/problem/C 题意:给一个角度ang(1<=ang&l ...
- [LUOGU] P1048 采药
题目描述 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了一个难题.医师把他带到一个到处都是草药的山洞里对他说:" ...
- GIMP中的新建Layer与更改Layer大小
这边可以直接New Layer,新建一个Layer,还可以New from Visible,第二种是将当前的状态下图像复制出来. 改变Layer的大小,一般的方法两种: Crop to Selecti ...
- 【mysql】配置 选项文件
在Windows中,MySQL程序从以下文件读取启动选项: 文件名 目的 WINDIR\my.ini 全局选项 C:\my.cnf 全局选项 INSTALLDIR\my.ini 全局选项 defaul ...