最小の削減とコストフロー

最小割:

ネットワークフローグラフの場合、グラフ全体が2つの部分に分割され、1つの部分にはソースポイントが含まれ、もう1つの部分にはシンクポイントが含まれます。分割方法はカットと呼ばます。

切断能力は、エッジを切断するときに切断されるエッジの能力の合計です。切断能力を最小化するカットは、最小カットと呼ばれます。

道を見つける:

ネットワークフローグラフの最小カットは最大フローに等しく、このブログをここ見ることができることを証明する方法については、私はあまり多くの食べ物を証明しません。
それらが等しいので、最大のフローのテンプレートを実行して、最小のカットを見つけることができます

一般的なモデル:


最小カットモデル、つまり2つのモデルのうちの1つを使用するLittleMのクロップについて質問があります。
このモデルは、大まかに言って、2つのセットに分割できるポイントセットがいくつかあり、AのコストはXXXで、BのコストはXXXです。

コストフロー:

コストフローとは、エッジごとに、フローを通過するときにチャージする必要があることです。チャージの数はフローに比例します。通常、問題は、各サイドがフローの各ユニットを通過するのにかかる時間です。

最小コストと最大フロー、MCMFアルゴリズム:

最小コストと最大フローは、フローが最大のときに可能な限りコストを削減することです。
通常のアプローチは、bfsの代わりにspfaを使用してから、最大フローを見つけることです。これがMCMFアルゴリズムです。
なぜあなたはこれをしたいのですか?

各エッジのコストはエッジの重みと見なすことができ、sからtへのフローは、エッジの重みと最小の拡張パスを見つけると見なすことができます。したがって、bfsの代わりにspfaを使用でき、最小コストと最大フローが不足します。

これが正しい理由については、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