题目链接

  哈  学会最小费用最大流啦

  思路是这样。

  首先我们有一个贪心策略。如果我们每次找到单位费用和最短的一条增广路,那么显然我们可以把这条路添加到已有的流量里去——不管这条路的流量是多大,反正它能扩大现有流量,而且目前为止它是可以扩大流量的所有路径中单位花费最少的。

  然后我们就把这条路填上。想想看当我们找不到这样一条路的时候会发生什么?

  那就是没有增广路了。恭喜我们获得最小费用最大流。这是为什么呢?

  首先没有任何一条增广路的时候我们肯定获得最大流没错

  然后我们回顾我们扩展的方式。每次我们都选择了一条单位费用和最短的路径,也就是说,我们总是先把便宜的路尽可能利用完了,才去利用那些贵的。鉴于此,我们总是已经把更便宜的填满了,整张图上没有更便宜的路了,才去尝试探索更贵的。

  那么这就是最小费用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找增广路)的更多相关文章

  1. 洛谷P3381 最小费用最大流模板

    https://www.luogu.org/problem/P3381 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用 ...

  2. luogu 3376 最小费用最大流 模板

    类似EK算法,只是将bfs改成spfa,求最小花费. 为什么可以呢,加入1-3-7是一条路,求出一个流量为40,那么40*f[1]+40*f[2]+40*f[3],f[1]是第一条路的单位费用,f[2 ...

  3. 【luogu P3381 最小费用最大流】 模板

    题目链接:https://www.luogu.org/problemnew/show/P3381 把bfs变成spfa #include <queue> #include <cstd ...

  4. HDU3376 最小费用最大流 模板2

    Matrix Again Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)To ...

  5. 最大流 && 最小费用最大流模板

    模板从  这里   搬运,链接博客还有很多网络流题集题解参考. 最大流模板 ( 可处理重边 ) ; const int INF = 0x3f3f3f3f; struct Edge { int from ...

  6. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

  7. 【网络流#2】hdu 1533 - 最小费用最大流模板题

    最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...

  8. poj 2195 最小费用最大流模板

    /*Source Code Problem: 2195 User: HEU_daoguang Memory: 1172K Time: 94MS Language: G++ Result: Accept ...

  9. POJ2135 最小费用最大流模板题

    练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include ...

随机推荐

  1. selenium的定位

    id定位  find_element_by_id()方法通过id来定位元素 例如: find_element_by_id("kw") find_element_by_id(&quo ...

  2. 基于BranchTraceStore机制的CPU执行分支追踪工具 —— CpuWhere [修正版 仅驱动]

    [前言] 在张银奎老师的<软件调试>一书中,详细地讲解了使用内存的分支记录机制——BTS机制(5.3),并且给出了示例工具CpuWhere及其源代码.但实际运行(VMware XP_SP3 ...

  3. UVALive 4287 Proving Equivalence (强连通分量)

    把证明的关系看出一张图,最终就是要所有的点都在至少一个环中.环的判断和度数有关. 用tarjan找强连通分量,在一个强连通分量点已经等价缩点以后形成一个DAG,计算入度为0的点数a, 出度为0的b,取 ...

  4. select *from where 和select *from jion on 语句的差别

    https://zhidao.baidu.com/question/541791438.html select 学号 a,成绩 a,姓名 b from 成绩表 a,学生表 b where a.学号=b ...

  5. NSCopying协议和copy方法

    不是所有的对象都支持 copy需要继承NSCopying 协议(实现 copyWithZone: 方法)同样,需要继承NSMutableCopying 协议才可以使用mutableCopy(实现 mu ...

  6. 【page-monitor 前端自动化 中篇】 源码分析

    转载文章:来源(靠谱崔小拽) 上篇中初探了page-monitor的一些功能和在前端自动化测试方面的可行性,本篇主要分析下page-monitor的实现方式和源码. mode-module简介 pag ...

  7. VC-基础:VC++动态链接库(DLL)编程深入浅出

    1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了“无库-静 ...

  8. Java中集合类

    一.Collection Collection 接口用于表示任何对象或元素组.想要尽可能以常规方式处理一组元素时,就使用这一接口.Collection 在前面的大图也可以看出,它是List 和 Set ...

  9. POI写入word docx 07 的两种方法

    下载最新jar包:http://poi.apache.org/download.html 以及API 1.写入word 1.1 直接通过XWPFDocument生成 在使用XWPFDocument写d ...

  10. Emmet:HTML/CSS代码快速编写神器--20150422

    Emmet的前身是大名鼎鼎的Zen coding,如果你从事Web前端开发的话,对该插件一定不会陌生.它使用仿CSS选择器的语法来生成代码,大大提高了HTML/CSS代码编写的速度,比如下面的演示: ...