让菜鸡讲一讲费用流(EK)

让我再讲一个故事吧。

又有一些小精灵要准备从银月城(S)迁徙到Nibel山(T)。

这两个地方之间的道路构成了一个网络。

每个道路都有它自己的容量,这决定了每天有多少小精灵可以同时从这儿通过。

和上一篇不同的是,由于上次迁徙的规模很大,

吸引了其它一些种族的注意,

这次每条道路都会有一些人/兽人/哥布林/...向精灵们征收过路费,

现在精灵们想知道,在花费最小的情况下,它们迁徙的速度最大是多少只每天。

费用流=最小费用最大

在要求流最大的情况下要求费用最小,好像原来的isap已经派不上用场了呢!

让我们回到最朴实的EK算法上。

EK算法每一次只寻找一条增广路,

这带给它解决这一个方面的问题的得天独厚的优势。

这是原来的EK算法:

int BFS()
{
    /*找到一条增广路*/
}
int ek()
{
    /*对找到的增广路进行一系列处理*/
}

我们用BFS找增广路。

想象一下,

既然要求费用最小

我们就把费用作为路径长度

之后每一次跑一遍最短路

那么就可以保证花费最小了!



所以,我们只要把原来的BFS()改成spfa()或者dijkstra()就好啦

ps.一般dijkstra只能跑不带负权边的图,
但是有一种特殊的技巧可以把边权魔改成正的。

以下是拿辣鸡spfa跑的费用流

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define mp(a,b) make_pair(a,b)
#define ll first
#define rr second
inline int gotcha()
{
    register int a=0,b=1,c=getchar();
    while(!isdigit(c))b^=a=='-',c=getchar();
    while(isdigit(c))a=a*10+c-48,c=getchar();
    return b?a:-a;
}
const int _ = 5002 , __ = 50002<<1 , inf = 0x3f3f3f3f;
int to[__],ne[__],v[__],co[__],he[__]={0},ecnt=1;
int n,m,dis[_],pe[_],pv[_],S,T;
bool ed[_];
void adde(int a,int b,int c,int d){to[++ecnt]=b,v[ecnt]=c,co[ecnt]=d,ne[ecnt]=he[a],he[a]=ecnt;}
queue<int> q;
int spfa()
{
    memset(dis,63,sizeof(dis)),memset(ed,0,sizeof(ed));
    while(!q.empty())q.pop();
    register int i,a;
    q.push(S),ed[S]=1,dis[S]=0;
    while(!q.empty())
    {
        a=q.front(),q.pop();ed[a]=0;
        for(i=he[a];i;i=ne[i])
            if(v[i]>0 && dis[to[i]]>dis[a]+co[i])
            {
                dis[to[i]]=dis[a]+co[i];
                pe[to[i]]=i,pv[to[i]]=a;
                if(!ed[to[i]])ed[to[i]]=1,q.push(to[i]);
            }
    }
    return dis[T]<inf;
}
pii mfmc()
{
    register int i,sco=0,sfl=0,flw;
    while(spfa())
    {
        flw=inf;
        for(i=T;i!=S;i=pv[i])flw=min(flw,v[pe[i]]);
        for(i=T;i!=S;i=pv[i])v[pe[i]]-=flw,v[pe[i]^1]+=flw;
        sco+=flw*dis[T],sfl+=flw;
    }
    return mp(sfl,sco);
}
int main()
{
    register int i,j,k,a,b;
    register pii tmp;
    n=gotcha(),m=gotcha(),S=gotcha(),T=gotcha();
    for(i=1;i<=m;i++)
    {
        j=gotcha(),k=gotcha(),a=gotcha(),b=gotcha();
        adde(j,k,a,b),adde(k,j,0,-b);
    }
    tmp=mfmc();
    printf("%d %d",tmp.ll,tmp.rr);
    return 0;
}

这就不写伪代码了吧!?

以后补

原文地址:https://www.cnblogs.com/finder-iot/p/8409010.html

时间: 2024-10-03 10:24:13

让菜鸡讲一讲费用流(EK)的相关文章

菜鸡程序猿的开始:java基础知识之一个简单ATM机

import java.util.Scanner; public class Atm{ static int allmoney=150000; //ATM现有余额 static int all=200000; // ATM最大量 static int money =10000; // 初始化用户的余额 public static void main(String[] args) { System.out.print("*********************************"

前端菜鸡关于 JS,Ajax,JSON,API,的一些思绪整理

header: 这是我的第一篇博客,希望这篇菜鸡总结能帮我找回该努力的方向吧.也许还能帮到几个和我境遇类似的大学狗?反正我现在是觉得这篇东西除了我不可能有别人会看了.hhhh... body: /*  7月29号加入了FreeCodeCamp学前端.大概倒推三个月在codecadymy学过python和JS的基础语法.倒推年初还把python和后端当做自己努力的方向.在知乎上听从建议去啃SCIP,结果第二章看到一半实在是被自己的数学打败了.又忙着考试和打游戏,大二的下学期就糊里糊涂的过去了.大学

hdu4322 candy 费用流

题意: n个糖果,m个孩子,给一个矩阵like[i][j]表示第i个孩子喜欢第j个糖果. 如果孩子拿到他喜欢的糖果,那么他将会增加k个快乐度,拿到不喜欢的,增加1. 如果孩子i的欢乐值大于B[i],那么他就是开心的. 问,能否有一种分配方案,让所有孩子都开心,有输出yes,没有no. 思路:(讲的不好请见谅,大牛勿喷) 起初是看了一个大牛的一篇关于网络流建模的总结,里面有个跟这个题同名的题,只是它里面k是固定的就是2.里面的做法是用单纯的最大流做的,没有考虑到费用.建图是这样的,每颗糖作为一个点

【BZOJ4849】[Neerc2016]Mole Tunnels 模拟费用流

[BZOJ4849][Neerc2016]Mole Tunnels Description 鼹鼠们在底下开凿了n个洞,由n-1条隧道连接,对于任意的i>1,第i个洞都会和第i/2(取下整)个洞间有一条隧道,第i个洞内还有ci个食物能供最多ci只鼹鼠吃.一共有m只鼹鼠,第i只鼹鼠住在第pi个洞内,一天早晨,前k只鼹鼠醒来了,而后n-k只鼹鼠均在睡觉,前k只鼹鼠就开始觅食,最终他们都会到达某一个洞,使得所有洞的ci均大于等于该洞内醒着的鼹鼠个数,而且要求鼹鼠行动路径总长度最小.现对于所有的1<=k

HDU 5045 费用流求最大权

点击打开链接 题意:有n个人和m到题目,每个人做对的概率以矩阵形式给出,问如何分配才可以使做对的概率最大,有一个限制条件是做到目前为止每两个人的做题数量差距不能超过1,也就是前n道题目,必须一人做一个 思路:网上都是dp多一点,用网络流也可以,不过麻烦很多,可是本弱是一点dp都不会的选手啊,只能用网络流了,对于那个限制条件,我们可以以前n道题建一次图,然后再来n个,不过就直接建完就可以了,然后我们要求的是什么呢,很明显是最大权,而最大费用最大流刚好可以解决,这里面的费用流有两种方法,用spfa找

渣渣菜鸡的蚂蚁金服面试经历(一)

蚂蚁金服 电话一面 1.自我介绍.自己做的项目和技术领域 2.项目中的监控:那个监控指标常见的哪些? 3.微服务涉及到的技术以及需要注意的问题有哪些? 4.注册中心你了解了哪些? 5.consul 的可靠性你了解吗? 6.consul 的机制你有没有具体深入过?有没有和其他的注册中心对比过? 7.项目用 Spring 比较多,有没有了解 Spring 的原理?AOP 和 IOC 的原理 8.Spring Boot除了自动配置,相比传统的 Spring 有什么其他的区别? 9.Spring Clo

菜鸡的入门史

这篇博客记录我是怎么误打误撞来到了编程世界,以及为什么决定以此为业,一方面作为博客输出,另一方面希望能给需要的同学当一篇经验贴参考. 发现格式有点问题,先将就看一下,学习了再调整. 目录: 一.个人背景介绍 二.第一次接触前端 三.转向后端 Java 四.总结 五.参考建议 一.个人背景介绍 既然作为参考,那么肯定是要全方位讲清楚的,尤其是个人背景,不谈个人基础背景的经验都是耍流氓,个人情况不一致,适合自己的不一定适合别人,有背景情况下可以大概明白误差,因此该经验仅供考,盲目复制可能引发不适.

菜鸡问offer所在何方

大三的时候就想写博客了,结果拖到研二快结束才开通博客,这拖延症也是没谁了!!! 真正刺激到我的是,最近找实习,辛苦了一个月一个offer也没有,感觉到作为菜鸡的无奈---互联网寒潮,菜鸡水里泡,大佬岸上笑. 这段时间每天都很焦虑,晚上睡的不踏实,总在思考未来,思考有没有未来. 将死之人总会回顾往事,绝望的人也是如此.回顾这两年的研究生生活,找不出丝毫亮点,丝毫有意义之处.本科学的软件工程,研究生期间基本上在推那几个公式,代码都没怎么写,真的是丢了自己的老本行,导致我现在甚至对编程感到一种很强的生

讲一讲什么叫阻塞非阻塞同步异步

1.讲一讲什么叫阻塞非阻塞同步异步全是用来形容方法的,形容一个方法返回值状态的. 2.io读取,网络读取,jdbc读取,这些流的操作都是bio的,都是阻塞的. 3.所以沃恩一般在处理io操作时,都采用多线程来提高bio的效率. 4.io操作,就是本地文件,网络,数据嘛嘛.所以在这三种读取数据时,都要采用多线程提高效率. 5.多线程处理阻塞方法时,只不过是避免了主线程的阻塞,但是让子线程,也就是处理每个http request的线程去发生阻塞了. 6.传统的古老的开发方式: 单线程执行阻塞方法->