二分图匹配入门

之前大一的时候有学姐讲过二分图匹配的匈牙利(Hungrain)算法,当时没理解。最近想补补图论,学习一下二分图匹配的匈牙利算法,其实挺简单的。

先弄清二分图匹配时重要的几个概念:

(1)交替路:从一个未匹配的顶点出发,依次经过未匹配边,匹配边...,这样由匹配边,非匹配边交替形成的路称为交替路。一定先理解这个概念,才能理解增广路的概念。

(2)增广路:从一个未匹配的顶点出发,沿交替路走,到达第一个未匹配顶点时到达终点,这个过程形成的路称为增广路。


增加匹配的关键在于在整个图中寻找增广路,如果找不到增广路,则已经找到最大匹配(Berge 定理)。否则,我们可以将增广路中所经过的边进行修改,若其原来是匹配边,则我们将其修改为未匹配边。若其原来是未匹配边,则将其变为匹配边。这样可以增加一对匹配。为什么呢?因为增广路上一定是匹配边比未匹配边少一条,可以根据定义想一想。有了这个性质,那么我们就只需要找增广路就行了。再根据Berge定理,就找到了最大匹配。看两幅图来感受一下寻找增广路增加匹配的例子:

二分图匹配入门_第1张图片

图1 图2

我们选择从左边的顶点集出发,第一个未匹配的顶点是 4,于是我们从4开始走交替路, 4->7->1->6, 到达6时没有路可以走了,但此时没有到达未匹配顶点,因此,从4出发没有找到增广路。所以我们从5出发, 5->9->2->10,这个时候我们找到了一条增广路,把5-9, 2-10由未匹配边变为匹配边,把2 - 9由匹配边变为未匹配边,看看这个时候是不是多了一条匹配?由于左边顶点集已经没有未匹配的顶点能扩展增广路,故此时匹配已经达到最大。


hdu 2063 是一道入门级的二分图匹配。实现算法中图的存储结构选择了邻接表。

 

#include
#include
#include

using namespace std;

const int MAX = 2048;

vector G[MAX];
typedef vector::iterator iterator_vi;
int matched[MAX];
int vis[MAX];
int n, m, k;

bool dfs(int u)
{
    for(iterator_vi i = G[u].begin(); i != G[u].end(); i++)
    {
        int v = *i;
        if(!vis[v])
        {
            vis[v] = 1;
            if(matched[v] == -1 || dfs(matched[v]))
            {
             //   printf("%d %d\n", u, v);
                matched[u] = v;
                matched[v] = u;
                return true;
            }
        }
    }
    return false;
}

int hungrain()
{
    int ret = 0;
    memset(matched, -1, sizeof(matched));
    for(int i = 1; i <= m; i++)
    {
        if(matched[i] == -1)
        {
            memset(vis, 0, sizeof(vis));
            if(dfs(i))
                ret++;
        }
    }
    return ret;
}

int main()
{
    freopen("in.txt", "r", stdin);
    while(~scanf("%d", &k))
    {
        if(k == 0) break;
        scanf("%d%d", &m, &n);

        for(int i = 1; i <= m; i++)
            G[i].clear();
        for(int i = 0; i < k; i++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            b += m;
            G[a].push_back(b);
        }
        printf("%d\n", hungrain());
    }
    return 0;

}



你可能感兴趣的:(算法,图论,二分图匹配)