EK算法(連接矩陣)

/**
    Edmonds-Karp算法是最簡單的網絡流算法,當然也比較慢複雜度爲O(V*E^2)
    編寫簡單而且很好理解。。後面還會貼最快的dinic 算法
    複雜度爲O(E*V^2)  ( E爲邊數,V爲點數)

    網絡流是個大學科,實在變化莫測,各種建圖技巧,可以說競賽考網絡流
    90%考建圖,圖建好了,直接套模板即可

    這裏只是簡單的網絡流模板而已
    真正的學問是把實際問題轉換爲網絡流問題

    百度百科裏這樣描述網絡流:
    網絡流 network flows網絡流的理論和應用在不斷髮展,出現了具有增益的流、
    多終端流、多商品流以及網絡流的分解與合成等新課題。網絡流的應用已遍及
    通訊、運輸、電力、工程規劃、任務分派、設備更新以及計算機輔助設計等衆多領域。

    據我所知:甚至炒股問題也可以轉換爲網絡流來搞

    由於我也只是能看懂模板套模板而已,真正對流的理解甚微,所以就不多說了,
    網絡流在競賽中很常見,屬於重點內容,圖中的一大分支,要引起足夠的重視

*/
//由於我是用手敲的,只做參考,還請自行嚴格測試

const int inf = 0x3f3f3f3f;
const int M = 100;  // 結點數

int map[M][M], ans, n;  //ans 爲最大流, n爲節點個數
int pre[M], que[M], vis[M];

bool bfs(int s, int t) {  //源點爲s, 匯點爲t
    int head=0, tail=1;
    memset(vis, 0, sizeof(vis));
    que[0] = s;         //加入源點
    vis[s] = true;
    while (tail > head) {
        int u = que[head++];
        for (int i=0; i<=n; i++) {
            if (!vis[i] && map[u][i]) {
                pre[i] = u;  //前驅節點
                if (i == t)  //到達匯點
                    return true;
                que[tail++] = i;
                vis[i] = true;
            }
        }
    }
    return false;
}

void end(int s, int t) {
    int i, sum = inf;
    for (i=t; i!=s; i=pre[i])
        sum = min(sum, map[pre[i]][i]);
    for (i=t; i!=s; i=pre[i]) {
        map[pre[i]][i] -= sum;
        map[i][pre[i]] += sum;
    }
    ans += sum;
}

void EK(int s, int t) { //調用EK()即可,nv 爲節點總數
    while (bfs(int s, int t))
        end(int s, int t);
}

/**
    注意:
    1、網絡流問題屬於有向圖問題,可是我見過無向圖的題目,
       直接按無向圖添邊即可,如果不行就用鏈接表存邊,後面會貼,
       不過如果遇到最小費的無向圖問題就必須用鏈接表了
    2、如有多個源點匯點,一般用0做源點,n+1做匯點,添無限容量邊
    3、map[][] 數組只能用一次, ans賦初值爲0
    4、最大流等於最小割,網絡流還可以解決二分圖匹配問題

    上面模板爲依然空間的模板,也是最好理解的一個模板,
    依然的代碼風格和我很類似,所以好多東西都抄襲他的,嘿嘿

    練習:POJ 1149 3281 1273  1459
*/

收藏於 2011-11-20
來自於百度空間

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