最小割&费用流

最小割:

对于一个网络流图,把整张图分割成两个部分,一部分包含源点,一部分包含汇点的分割方式叫做

割的容量即切割边时所切去边的容量之和,其中使割的容量最小的割叫做最小割

求法:

一张网络流图的最小割等于它的最大流,至于怎么证明可以看一下这篇博客这里本人太菜就不证明了。
既然知道了它们相等,那么就可以跑最大流的模板来找最小割了

常见模型:

小M的作物
上面有一道题,里面就用到了一个最小割的模型,即二选一模型。
这种模型大概就是,有一些点集可以被分到连个集合中,分到A花费为XXX,分到B花费为XXX。

费用流:

费用流就是对于每条边,经过流量时是需要收费的,收费的数目和流量成正比,通常题目给的都是每条边通过每单位流量需要花费多少。

最小费用最大流,MCMF算法:

最小费用最大流就是要求在流量最大时,尽可能的减少花费。
通常的做法就是用spfa代替bfs,然后求最大流,这就是MCMF算法。
为啥要这么做呢?

每条边的费用可以看做边的权重,从s流向t就可以看做找一条边权和最小的增广路。于是就可以用spfa代替bfs然后跑出来的就是最小费用最大流。

至于为什么这样正确,其实很明显,因为每次spfa跑出来的就是当前费用最低的增广路,所以把这些加起来就是一定是最小费用。

模板:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 1e6 + 5;
int h[maxn],n,m,s,t,cnt = 2;
int pre[maxn],incf[maxn],dis[maxn];//pre用于记录路径,incf记录流,dis记录费用
ll maxFlow,maxCost;
bool vis[maxn];
struct node{
    
    
    int cost,e,nex,flow;
}e[maxn * 2];
void add(int a,int b,int f,int cost){
    
    
    e[cnt].e = b;
    e[cnt].nex = h[a];
    e[cnt].cost = cost;
    e[cnt].flow = f;
    h[a] = cnt++;
}
bool spfa(){
    
    //spfa
    for(int i = 1; i <= n; i++)vis[i] = 0,dis[i] = INF;
    vis[s] = 1,dis[s] = 0,incf[s] = INF;
    queue<int> qu;
    qu.push(s);
    while(!qu.empty()){
    
    
        int tmp = qu.front();
        vis[tmp] = 0;
        qu.pop();
        for(int i = h[tmp]; i ; i = e[i].nex){
    
    
            int endd = e[i].e;
            if(!e[i].flow)continue;//如果没残余流量了就不走
            if(dis[endd] > dis[tmp] + e[i].cost){
    
    
                pre[endd] = i;
                dis[endd] = dis[tmp] + e[i].cost;
                incf[endd] = min(incf[tmp],e[i].flow);
                if(!vis[endd])qu.push(endd),vis[endd] = 1;
            }
        }
    }
    if(dis[t] == INF)return 0;
    else return 1;
}

void MCMF(){
    
    //MCMF本体
    while(spfa()){
    
    
        int x = t;
        maxCost += (ll)dis[t] * incf[t];//最小费
        maxFlow += incf[t];//最大流
        while(x != s){
    
    //更新所有路径的流的状况
            e[pre[x]].flow -= incf[t];
            e[pre[x] ^ 1].flow += incf[t];
            x = e[pre[x] ^ 1].e;
        }
    }
}
/*
4 5 1 4
3 1 3
3 1 2
2 3 2
3 4 3
4 2 1
*/
题目:

最近写到的一道多校题目:这里
一道很不错的最小费用最大流的变形

猜你喜欢

转载自blog.csdn.net/qq_36102055/article/details/107383178