二分图匹配之 匈牙利算法简单学习后感

 

 

匈牙利算法的核心就是 增广路定理,能够理解增广路定理其实就理论理解了 匈牙利算法。

讲匈牙利算法的文章很多了,就不在这里关公面前耍大刀了。

 

个人对匈牙利算法的理解:

  先将图分为左边的点,和右边的点以后。

  对左边的每一个没有匹配的点,进行搜索是否有增广路,如果搜寻到了, 就可以   使当前这个左边的点成为匹配点的同时,使匹配边数+1

 

  可能我这么说也没有说清楚,网上有大牛的更好的讲解的文章,帮助会更大一些。我想说的是  匈牙利算法由于题目出现的两个情况,而出现的两个写法。

 

  一种就是简单版本。

  题目例子是:

  HDU 1068  男孩和女孩:http://acm.hdu.edu.cn/showproblem.php?pid=1068

 

  这种题目的特点就是:  构成二分图的 左边点和右边点,是混在一起编号,然后给你的。  

  这样一来,左边的点和右边的点不用分清。 对所有点进行  增广路搜索(DFS)就好了。

  代码里的两个数组:

                                      book    是  每一次增光路搜索,判断点有没有搜过

                                      ans      是  在整个过程中,   记录了每个点的匹配点是什么。                       

                                                          PS:  二分图匹配过程中,每个点要么没有匹配点,要么有且只有一个匹配点

 

这是我的在这种情况的代码,不是本题的代码....

 

#include"cstdio"
#include"cstring"
#include"vector"
using namespace std;
#define inf 99999
int n,m; //点,边
int res; //匹配数
int ans[inf]; //各点对应妻子,or -1
int book[inf]; //交替路标记
vectoredge[inf];

int dfs(int u)
{
    int len=edge[u].size();
    for(int i=0;i

 

 

 

 

 

 

  还有一种情况应该更大众吧,就是 左边的点和右边的点 分开编号给出,都从0或者1 开始编号

  这样子就不能一股脑的搜索了。有可能做题的人没有意识到,但是用上面的办法去做应该会很乱很扯....

  而且我看到了  kuangbin大神的代码,一直没看懂。  后来自己想通了,很幸运发现和kuangbin大神的想法是一样的.....

  题目例子是:

  POJ 1469:http://poj.org/problem?id=1469              课程匹配问题。

 

   因为题目已经分好了左边的点和右边的点。

  所以对每个左边的点进行搜索。             

                                  去掉了判断这个点是不是没有匹配点。

                                 因为,每个点起初都是没有匹配的。而当前点,是不可能被前面的点 给变成匹配点的。 

                                  这个判断也就显得多余。

 

  这里面的两个数组:

                                     book  表示 每一次搜索中,右边的点有没有被 搜索过

                                     ans    表示  整个过程中 , 右边的点 对应的  匹配点!!

 

  这个情况下的代码:(饿,是此题的代码)

#include"cstdio"
#include"cstring"
#include"vector"
using namespace std;
#define inf 999999999
#define loop(x,y,z) for(x=y;xedge[109];
void init()
{
    sum=0;
    memset(ans,-1,sizeof ans);
    int i;
    loop(i,1,p+1)edge[i].clear();
}

int dfs(int v)
{
    int i,len;
    len=edge[v].size();
    loop(i,0,len)
    {
        int u=edge[v][i];
        if(!book[u])
        {
            book[u]=1;
            if(ans[u]==-1||dfs(ans[u]))
            {
                ans[u]=v;
                return 1;
            }
        }
    }
    return 0;
}

void XYL()
{
    int i;
    loop(i,1,p+1)
    {
        memset(book,0,sizeof book);
        sum+=dfs(i);
    }
}

int main()
{
    int i,j,T,k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&p,&n);
        init();
        loop(i,1,p+1)
        {
            scanf("%d",&j);
            while(j--)
            {
                scanf("%d",&k);
                edge[i].push_back(k);
            }
        }
        XYL();
        if(sum==p)
        printf("YES\n");
        else
        printf("NO\n");
    }
    return 0;
}

 

 

 

 

 

 

你可能感兴趣的:(二分图匹配)