1. 程式人生 > >網路流最大流最小割演算法

網路流最大流最小割演算法

不得不說網路流演算法是很讓人無語的演算法,要想高效率竟然要非遞迴實現深搜,很無奈,到現在還是在低效率中掙扎!

最大流演算法的證明就不說了,無非就是最大流最小割定理的推導,定理描述如下:

對於任意給定的網路D=(V,A,C),從出發點vs到收點vt的最大流的流量必等於分割的最小截集的容量! 

至於截集,定義為:

給定網路D=(V,A,C),若點集V被分割成兩個非空集合V1和V2,使得V=V1+V2,V1

V2=φ(空集),且vs∈V1,vt∈V2,則把始點在V1,終點在V2的弧的集合稱為分離vs和vt

一個截集

然後,網路流演算法最重要的增廣鏈,正式定義為:

設 f = {Fij}是網路D=(V,A,C)上的一個可行流,u 是從 Vs到 Vt的一條鏈,若u 滿足下列條件:

(1)在弧 (vi,vj)∈μ+上,即 u+中的每一條弧都是非飽和弧;

(2)在弧 (vi,vj)∈μ-上,即u- 中的每一條弧都是非零流弧。

則稱 是關於 的一條增廣鏈

最大流就是不斷的找增廣鏈,直到找不到增廣鏈為止!

樸素的有Ford —— Fulkerson標號法,就是每次從源點開始找增廣鏈,然後更新網路,再找增廣鏈,再更新。。。

虛擬碼可以表示為:

void Ford_Fulkerson()

{

        int max_l = 0;

        while (存在增廣鏈)

        {

                max_l += 可更新流量;

                更新殘餘網路;

        }

}

另外網路流演算法多種多樣,比如dinic,有興趣可以學習學習!

程式碼如下:

#include <iostream>
#include <cstring>
#include <cstdlib>

using namespace std;

const int Max = 225;
const int oo = 210000000;

int n,m,c[Max][Max],r[Max][Max],source,sink,nc,np;
int dis[Max],block[Max];

void initialize()// BFS建立層次圖,
{
     int q[Max],head = 0, tail = 0;
     for(int i = 0; i <= sink; i++) dis[i] = oo;
     q[++head] = sink;
     dis[sink] = 0;
     while(tail < head)
     {
         int u = q[++tail], v;
         for(v = 0; v <= sink; v++)
         {
               if(dis[v] == oo && r[v][u] > 0)
               {
                   dis[v] = dis[u] + 1;
                   q[++head] = v;
               }