网络流之费用流问题

费用流即最小费用最大流

先贴上粉书上的模板:

struct Edge
{
    int from,to,cap,flow,cost;
    Edge(int u,int v,int c,int f,int w):
        from(u),to(v),cap(c),flow(f),cost(w)
        {}
};

int n,m;
vector<Edge> edges;
vector<int> G[maxn];
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn];

void init(int n)
{
    //this->n=n;    粉书上原版有这一句,但明显会报错。感觉去掉也没什么影响...
    for (int i=0;i<n;i++)
        G[i].clear();
    edges.clear();
}

void AddEdge(int from,int to,int cap,int cost)
{
    edges.push_back(Edge(from,to,cap,0,cost));
    edges.push_back(Edge(to,from,0,0,-cost));
    m=edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}

bool BellmanFord(int s,int t,int &flow,long long &cost)        //用队列优化过,感觉和SPFA一样了
{
    for (int i=0;i<n;i++)   d[i]=INF;
    memset(inq,0,sizeof(inq));
    d[s]=0;     inq[s]=1;       p[s]=0;     a[s]=INF;

    queue<int> Q;
    Q.push(s);
    while (!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        inq[u]=0;
        for (int i=0;i<G[u].size;i++)
        {
            Edge& e=edges[G[u][i]];
            if (e.cap>e.flow && d[e.to]>d[u]+e.cost())
            {
                d[e.to]=d[u]+e.cost;
                p[e.to]=G[u][i];
                a[e.to]=min(a[u],e.cap-e.flow);
                if (!inq[e.to])
                {
                    Q.push(e.to);
                    inq[e.to]=1;
                }
            }
        }
    }
    if (d[t]==INF)      return false;
    flow+=a[t];
    cost+=(long long)d[t] * (long long)a[t];
    for (int u=t;u!=s;u=edges[p[u]].from)
    {
        edges[p[u]].flow+=a[t];
        edges[p[u]^1].flow-=a[t];
    }
    return true;
}

int MCMF(int s,int t,long long& cost)        //s:起点;t:汇点;
{
    int flow=0;     cost=0;            //flow:求出来的最大流      cost:求出来的费用
    while (BellmanFord(s,t,flow,cost));
    return flow;
}

Exercise:POJ2516

网络流之费用流问题,布布扣,bubuko.com

时间: 2024-10-17 13:33:27

网络流之费用流问题的相关文章

NEU 1458 方格取数(网络流之费用流)

题目地址:NEU 1458 跟杭电上的那两个方格取数不太一样..这个可以重复,但是取和的时候只能加一次.建图思路基本一会就出来.同样的拆点,只不过这题需要再拆个边,其中一条费用0,另一条费用为那个点处的值.流量都限制为1.然后剩下的都跟杭电上的那两个差不多了.因为把数组开小了WA了好几发..(我前面居然还专门检查了一下数组大小,居然当时还认为没开小...对自己无语..) 代码如下: #include <iostream> #include <stdio.h> #include &l

HDU 4406 GPA(网络流-最大费用流)

GPA Problem Description GPA(Grade-Point Average) is one way to measure students' academic performance in PKU. Each course has an integer credit, ranges from 1 to 99. For each course, you will get a score at the end of the semester, which is an intege

HDU 3667 Transportation(网络流之费用流)

题目地址:HDU 3667 这题的建图真是巧妙...为了保证流量正好达到k,需要让每一次增广到的流量都是1,这就需要把每一条边的流量都是1才行.但是每条边的流量并不是1,该怎么办呢.这个时候可以拆边,反正c最多只有5,拆成5条流量为1的边.但是这时候费用怎么办呢,毕竟平方的关系不能简单把每一条边加起来.这时候可以把拆的边的流量设为1,3,5,7,9.如果经过了3个流量,那就肯定会流1,3,5,费用为9,是3的平方,同理,其他的也是如此.然后按照给出的边建图跑一次费用流就可以了. 代码如下: #i

POJ 2516 Minimum Cost(网络流之费用流)

题目地址:POJ 2516 我晕啊...这题一上来就想到了对每种货物分开求..但是马上就放弃了..感觉这样求50次费用流太耗时..后来就果断拆点,拆了好长时间,一直TLE..即使降到了2600个点也TLE..然后又想起了这个分开求的方法,又突然觉得100个点的费用流几乎不费什么时间..最多也只是求50次而已,还是可以试试的..于是一试居然还真过了... 说到这里,思路应该已经知道了吧.就是对每种货物分开求,因为每种货物是相互独立的.每一次的建图思路就是: 源点与供应商连边,流量权值为供应商这种货

POJ 3422 Kaka&#39;s Matrix Travels(网络流之费用流)

题目地址:POJ 3422 方法是对每个点i拆点成i'和i'',然后对每个i'和i''连一条费用为该点值,流量为1的边,再连1条费用为0,流量为k-1的边. 然后对每个点与右边下边相邻的点连边,流量均为INF,费用均为0.需要再建一源点与汇点,对于k次只需要在源点与汇点处进行限制即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #inclu

有上下界的、有多组源汇的、网络流、费用流问题

先默认读者有基础的网络流以及费用流的知识前置 1.有上下界无源点汇点的可行流问题: 在本文中指: 原图中没有任何一个点可以凭空产生流量,亦没有任何一个点可以凭空消灭流量: 存在边既有流量上界又有流量下界: 求每条边流量的一组可行解: 满足每个点的入流量等于出流量: 由题意可见本题的图中有环,于是此类问题也被称作循环流: 这里给出的解法是将本题转换为一道普通的有上界最大流问题: 修改本题原图中每条边的流量下界为0,上界为原上界-原下界: 视为该边现在已经拥有了等同于该边流量下界的基础流量了, 然而

洛谷P4003 无限之环(infinityloop)(网络流,费用流)

洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ? m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格子某些方向的边界的中点有接口,所有水管的粗细都相同,所以如果两个相邻方格的共边界的中点都有接头,那么可以看作这两个接头互相连接.水管有以下 15 种形状: 游戏开始时,棋盘中水管可能存在漏水的地方. 形式化地:如果存在某个接头,没有和其它接头相连接,那么它就是一个漏水的地方. 玩家可以进行一种操作:

HDU 2686 &amp;&amp; HDU 3376(网络流之费用流)

题目地址:HDU 2686       HDU 3376 这两道题目除了数据大小外是一样的.前者只有30*30,但是后者却成了600*600..本来以为前者代码用到后者会超时,迟迟没敢交,但是感觉能用费用流的话也只能这么做了,于是改了改数组大小就交上去了.还真没超时.. 这题又是一道关于来回最短路的.最大费用可以把费用改成相反数,最后再转成相反数就是最大费用了. 建图思路是拆点,限制每个点只能经过一次.然后将每个点与右边的和下边的连边.源点与汇点要设为2个流量. 不知道为什么用G++叫就一直WA

POJ 2135 Farm Tour(网络流之费用流)

题目地址:POJ 2135 来回走一遍可以看成从源点到汇点走两遍.将每个点的流量设为1,就可以保证每条边不重复.然后跑一次费用流就行了.当流量到了2之后停止,输出此时的费用. #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <qu