最大流的Edmonds-Karp算法

最大流的問題描述可以對比參照水在水管中的流動。從源(圖中唯一的入度爲0的點)流到匯(圖中唯一出度爲0的點)。每條水管都有限定的容量,要求最多能有“多少”水同時流動到匯。

最大流的一種比較優的解法時Edmonds-Karp算法,不斷找一條源到匯的路徑,若有,找出增廣路徑上每一段[容量-流量]的最小值delta,然後構建殘餘網絡,再在殘餘網絡上尋找新的路徑,增加總流量,形成新的殘餘網絡,再尋找新路徑…..直到某個殘餘網絡上找不到從源到匯的路徑爲止,最大流就算出來了。通俗來說,當我們通過搜索找到一條從起點(源)到終點(匯)的路徑後,我們把路徑上每條正向邊都減掉算出來的流量值,同時反向邊加上算出來的流量值,然後再次搜索找新的路徑直到沒有辦法找到,每次都加上搜索出來的流量值即可。

附上代碼:



#include <iostream>  
#include <queue>  
#include<cstring> 
#include<cstdlib>
#include<cstdio>
#include<algorithm> 
using namespace std;  
#define arraysize 201  
int maxData = 0x7fffffff;  
int capacity[arraysize][arraysize]; //記錄殘留網絡的容量  
int flow[arraysize];      //標記流動到當前節點後還有多少流量可以流動
int pre[arraysize];       //標記在這條路徑上當前節點的前驅,同時標記該節點是否在隊列中  
int n,m;  
queue<int> Q;  
int BFS(int s,int t)  
{   
    while(!Q.empty())       //隊列清空  
        Q.pop();  
    for(int i=1;i<m+1;++i)  
    pre[i]=-1;  
    pre[s]=0;  
    flow[s]= maxData;  
    Q.push(s);  
    while(!Q.empty())  
    {  
        int index = Q.front();  
        Q.pop();  
        if(index == t)            //找到了增廣路徑  
            break;  
        for(i=1;i<m+1;++i)  
        {  
            if(i!=s && capacity[index][i]>0 && pre[i]==-1)  
            {  
                 pre[i] = index; //記錄前驅  
                 flow[i] = min(capacity[index][i],flow[index]);   //關鍵:迭代的找到增量  
                 Q.push(i);  
            }  
        }  
    }  
    if(pre[t]==-1)      //殘留圖中不再存在增廣路徑  
        return -1;  
        return flow[t];  
}  
int maxFlow(int s,int t)  
{  
    int incr= 0;  
    int sum= 0;  
    while((incr=BFS(s,t))!=-1)  
    {  
         int k = t;          //利用前驅尋找路徑  
         while(k!=s)  
         {  
              int last = pre[k];  
              capacity[last][k] -= incr; //改變正向邊的容量  
              capacity[k][last] += incr; //改變反向邊的容量  
              k = last;  
         }  
         sum += incr;  
    }  
    return sum;  
}  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章