帶花樹演算法--一般圖最大匹配_帶花樹

來源:互聯網
上載者:User

可以在uoj#79測試模板題
如標題,簡單地介紹一下帶花樹演算法,提供一個自認為不錯的模板
安利一篇介紹得很詳細的blog
由於本人實在太蒻。。。這篇blog就不講述任何關於演算法正確性的證明吧
(也許以後會有興趣翻譯原論文: EfficientAlgorithmsforFindingMaximalMatchinginGraphs ,不過現在肯定是懶了。。)

可能有些選手會想苟蒻我一樣懶,二分圖匹配只會用Dinic做法,建議學習帶花樹之前看一下匈牙利演算法
就像匈牙利演算法一樣,帶花樹演算法的核心也是類似地每次找增廣路
假設對於原圖的k個點,已經找到了一些匹配,先把這些匹配留著
選擇一個尚未匹配的點s,作為起點,進行bfs,保留bfs樹
每次遍曆到一個點,如果它也沒匹配,那非常棒。因為這樣就找到了一條增廣路,直接增廣即可。
否則,記這個點為u,記它的配偶為v
對點u,標記為T節點,對於v,標記為S節點,並把v入隊,繼續bfs
(帶上起點s,顯然,每時每刻在隊列中的點都是S類節點)
那麼得到的bfs樹畫出來大概就是這樣的

其中紅色節點為起點
顯然,有的時刻,從某個點出發,路徑上下一個點是被訪問過的,哪怎麼辦。
對這個節點分類討論
1.這個點是T節點

就像圖中藍線串連的邊,顯然,此時找到了一個偶環,忽略即可

2.這個點是S節點

還是圖中的藍線,此時就找到了一個長度為奇數的環
不過這時候的情況並不簡單。。。顯然,找不到一個方案構造增廣路
但是,如果這個環上存在任意一個點,使得這個點串連的點中存在一個未匹配點
那麼顯然,此時可以構造出一條一路回溯的增廣路
那麼,這個時候這個奇環上任意一個點有邊串連未匹配點都是等價的
於是,可以將這個奇環縮成一個新點,然後再繼續進行bfs,直到找到增廣路為止(或是證明不存在)

至此,帶花樹演算法求解一般圖匹配的基本步驟就大致清晰了
bfs->縮環->bfs->縮環->…->縮環->bfs->找到增廣路
那麼找到增廣路時,就是沿路將匹配情況取反,以及,我們需要把沿途經過的環(帶花樹的花)一個個展開。。。。。。
完全沒有寫的慾望。。不知代碼從何下手。。。
這邊提供一個本人認為較容易實現的板子。。(反正這個演算法都是靠板子。)

首先,對於每次選擇的bfs起點,1~n for一遍就行了
每次判斷當前點是否已配對,如果沒有,才進行bfs
對於每個遍曆到的T類點,記錄pre[i]為找到它的S類點編號
每次出現S找到S的情況就需要進行縮環
對於縮出來的環,只找一個環上的S點作為它的代表點
如果一朵花被包含在另一朵花內,那麼這朵花就不再表示出來了
其實我們不需要真正地去做這個縮環的過程,
只需要對每朵花內的pre數組進行適當修改就行了
大概如圖所示:

這是一個S找到S的情形
只需要大力將每個S的pre邊連上就行了
顯然,如果一個點找到了合法的匹配對象(即一個未匹配點)
我們可以很輕鬆的通過pre邊把需要修改的環修改掉
具體操作不妨參考本人代碼中的函數
Link 為縮環函數
Rebuild 為上述需要更改的pre邊
Augment 則為增廣函數

#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<stack>#include<bitset>using namespace std;const int N = 505;int n,m,cnt,Num[105][7],fa[N],pre[N],Mark[N],mat[N],vis[N];queue <int> Q;vector <int> v[N];inline int Getfa(int x){    return x == fa[x] ? x : fa[x] = Getfa(fa[x]);}inline int getint(){    char ch = getchar(); int ret = 0;    while (ch < '0' || '9' < ch) ch = getchar();    while ('0' <= ch && ch <= '9')        ret = ret * 10 + ch - '0',ch = getchar();    return ret;}void Build(){    n = getint(); m = getint();    while (m--)    {        int x = getint(),y = getint();        v[x].push_back(y); v[y].push_back(x);    }}inline void Augment(int p){    while (p != -1)    {        int tmp = mat[pre[p]]; mat[p] = pre[p];        mat[pre[p]] = p; p = tmp;    }}inline void Rebuild(int x,int y,int lca){    while (Getfa(x) != lca)    {        pre[x] = y;        if (fa[x] == x) fa[x] = lca;        if (fa[mat[x]] == mat[x]) fa[mat[x]] = lca;        if (Mark[mat[x]] == 1) {Q.push(mat[x]); Mark[mat[x]] = 0;}        y = mat[x]; x = pre[y];    }}inline void Link(int x,int y){    ++cnt; int p = Getfa(x);    for (;;)    {        vis[p] = cnt; p = mat[p];        if (p == -1) break; p = Getfa(pre[p]);    }    int lca; p = Getfa(y);    for (;; p = Getfa(pre[mat[p]]))        if (vis[p] == cnt) {lca = p; break;}    Rebuild(x,y,lca); Rebuild(y,x,lca);}inline int BFS(int s){    for (int i = 1; i <= n; i++)        fa[i] = i,Mark[i] = pre[i] = -1;    while (!Q.empty()) Q.pop(); Mark[s] = 0; Q.push(s);    while (!Q.empty())    {        int k = Q.front(); Q.pop();        for (int i = 0; i < v[k].size(); i++)        {            int to = v[k][i];            if (Getfa(to) == Getfa(k)) continue;            if (Mark[to] == -1)            {                Mark[to] = 1; pre[to] = k;                if (mat[to] == -1)                {                    Augment(to); return 1;                }                Mark[mat[to]] = 0; Q.push(mat[to]);            }            else if (Mark[to] == 0) Link(to,k);        }    }    return 0;}int main(){    #ifdef DMC        freopen("DMC.txt","r",stdin);    #endif    int Ans = 0; Build();    for (int i = 1; i <= n; i++) mat[i] = -1;    for (int i = 1; i <= n; i++)        if (mat[i] == -1) Ans += BFS(i);    cout << Ans << endl;    for (int i = 1; i <= n; i++)        printf("%d%c",mat[i] == -1 ? 0 : mat[i],i == n ? '\n' : ' ');    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.