求二分圖最大匹配——Hopcroft-Krap演算法

來源:互聯網
上載者:User

標籤:flag   push   res   尋找   eof   turn   memset   pre   二分圖最大匹配   

本文是對二分圖大講堂這篇文章中Hopcroft-Krap演算法代碼實現的詳細注釋。

HK演算法的基本原理

Hopcroft-Karp演算法先使用BFS尋找多條增廣路,然後使用DFS遍曆增廣路(累加匹配數,修改匹配點集),迴圈執行,直到沒有增廣路為止。
Hopcroft-Karp演算法的BFS遍曆只對點進行分層(不標記是匹配點和未匹配點),然後用DFS遍曆看上面的層次哪些是增廣路徑(最後一個點是未匹配的)。
BFS過程可以看做是映像樹結構一樣逐層向下遍曆,還要防止出現相交的增廣路徑。

二分圖大講堂中給出了HK演算法步驟的通俗解釋

設U和V是圖G的二分圖,M是從U到V的匹配
(1)使用BFS遍曆對圖的點進行分層,從X中找出一個未匹配點v,(所有v)組成第一層,接下的層是這樣形成的——都是尋找匹配點(增廣路性質),直到在V中找到未匹配點才終止尋找,對X其他未匹配點同樣進行尋找增廣路徑(BFS只分層不標記是否匹配點)
(2)使用DFS遍曆尋找(1)形成的增廣路,找到就匹配數就累加1
(3)重複(1)(2)操作直到找不出增廣路徑為止

而二分圖最大匹配之Hopcroft-Karp演算法裡給了比較學術化的步驟,有興趣可以看一下

代碼註解如下

#include <bits/stdc++.h>using namespace std;const int MAXN = 1e5 + 10;const int INF = 0x3f3f3f3f;bool flag;int p, n;// 兩個集合: X和Y// Mx,My記錄結點的匹配頂點int Mx[MAXN], My[MAXN], Nx, Ny;// dx,dy是結點的BFS遍曆層次int dx[MAXN], dy[MAXN], dis;bool vst[MAXN], g[110][310];bool searchP(){    queue<int> Q;    dis = INF;    memset(dx, 0x3f, sizeof dx);    memset(dy, 0x3f, sizeof dy);    // 使用BFS遍曆對圖的點進行分層,從X中找出一個未匹配點v    // (所有v)組成第一層,接下來的層都是這樣形成——每次尋找    // 匹配點(增廣路性質),直到在Y中找到未匹配點才停止尋找,    // 對X其他未匹配點同樣進行尋找增廣路徑(BFS只分層不標記    // 是否匹配點)    // 找出X中的所有未匹配點組成BFS的第一層    for (int i = 1; i <= Nx; ++i)    {        if (Mx[i] == -1)        {            Q.push(i);            dx[i] = 0;        }    }    while (!Q.empty())    {        int u = Q.front();        Q.pop();        // 該路徑長度大於dis,等待下一次BFS擴充        // dis是到Y集合的長度,所以dis一定是一個奇數        // 而每次調用searchP只會遍曆一層X集合結點        if (dx[u] > dis) break;        for (int v = 1; v <= Ny; ++v)        {            // (u,v)之間有邊且v還沒有分層            // 分配v的層次            if (g[u][v] && dy[v] == -1)            {                dy[v] = dx[u] + 1;            }            // v是未匹配點,停止延伸(尋找)            // 得到本次BFS的最大遍曆層次            if (My[v] == -1) dis = dy[v];            // v是匹配點,繼續延伸            else            {                dx[My[v]] = dy[v] + 1;                Q.push(My[v]);            }        }    }    // 若dis為INF說明Y中沒有未匹配點,也就是沒有增廣路徑了    return dis != INF;}// 用DFS遍曆尋找BFS形成的增廣路,如果可以找到增廣路就停止遍曆並返回truebool DFS(int u){    for (int v = 1; v <= Ny; ++v)    {        if (!vst[v] && g[u][v] && dy[v] == dx[u] + 1)        {            vst[v] = 1;            // 層次(也就是增廣路徑的長度)大於本次尋找的dis            // 是searchP中被break的情況,也就是還不確定是否是增廣路            // 只有等再次調用searchP再判斷            if (My[v] != -1 && dy[v] == dis) continue;            // 是增廣路徑,更新匹配集            if (My[v] == -1 || DFS(My[v]))            {                My[v] = u;                My[u] = v;                return true;            }        }    }    return false;}// 尋找二分圖的最大匹配int MaxMatch(){    int res = 0;    // 每個結點的匹配頂點置空    memset(Mx, 0x3f, sizeof Mx);    memset(My, 0x3f, sizeof My);    // 如果BFS可以找到增廣路徑    while (searchP())    {        memset(vst, 0 , sizeof vst);        for (int i = 1; i <= Nx; ++i)        {            // 用DFS尋找增廣路徑,增廣路徑一定從未匹配點開始            // 如果尋找到一個增廣路徑,匹配數加一            if (Mx[i] == -1 && DFS(i))                ++res;        }    }    return res;}

求二分圖最大匹配——Hopcroft-Krap演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.