zoukankan      html  css  js  c++  java
  • 匈牙利算法-二分图的最大匹配

    匈牙利(Hungarian)算法-二分图的最大匹配问题


    首先是一个小的讲解视频

    上述视频涉及到的一个打卡题目杭电OJ-2063-过山车

    我的代码如下:(下面的代码同视频里的稍有不同,或者说是男女正好相反吧)

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 505;
    int dict[maxn][maxn];
    int vis[maxn];
    int nxt[maxn];//某个男生有没有女生 
    int k,m,n;//m女生,n男生 
    
    
    bool match(int x)
    {
    	for(int i=1;i<=n;i++)//遍历每个男生 
    	{
    		if(dict[x][i] && !vis[i])//如果x女生对男生有意向且该男生还没有被访问过
    		{
    			vis[i]=1;//该男生在该女生的匹配阶段已经被访问过
    			if(nxt[i]==0 || match(nxt[i]))//如果男生没有被配对或者该男生配对的女生可以变换
    			{
    				nxt[i]=x;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    int solve()
    {
    	int sum = 0;
    	for(int i = 1;i<=m;i++)//遍历每个女生 
    	{
    		memset(vis,0,sizeof(vis));
    		if(match(i))sum++;
    	}
    	return sum;
    }
    
    int main()
    {
    	while(cin>>k && k)
    	{
    		//读入数据
    		memset(dict,0,sizeof(dict));
    		cin>>m>>n;
    		for(int i=0;i<k;i++)
    		{
    			int g,b;
    			cin>>g>>b;
    			dict[g][b]=1;
    		}
    		//初始化
    		memset(nxt,0,sizeof(nxt)); 
    		//解决问题
    		cout<<solve()<<endl; 
    	}
    	return 0;
    }
    

    其实,上面那个视频并没有过多的涉及到匈牙利算法的内容,
    也没有很好的讲明白递归算法的实现。
    不过,这至少让你对匈牙利算法的大致思想有所了解。
    下面,将会详细说明匈牙利算法及其前置概念。


    接下来是一个CSDN的博文。
    这个博客完全没有代码,但是它十分清晰的讲解了匈牙利算法算法精髓。

    博客链接

    注意算法关键词:二部图(二分图)、增广路、递归、后来者居上


    结合上面的解释以及打卡题目的代码,我们可以基本得到一个模板:

    const int MAXN = 500;
    int M, N;            //M, N分别表示左、右侧集合的元素数量
    int Map[MAXM][MAXN]; //邻接矩阵存图
    int p[MAXN];         //记录当前右侧元素所对应的左侧元素
    bool vis[MAXN];      //记录右侧元素是否已被访问过
    
    bool match(int i)
    {
        for (int j = 1; j <= N; ++j)
            if (Map[i][j] && !vis[j]) //有边且未访问
            {
                vis[j] = true;                 //记录状态为访问过
                if (p[j] == 0 || match(p[j])) //如果暂无匹配,或者原来匹配的左侧元素可以找到新的匹配
                {
                    p[j] = i;    //当前左侧元素成为当前右侧元素的新匹配
                    return true; //返回匹配成功
                }
            }
        return false; //循环结束,仍未找到匹配,返回匹配失败
    }
    
    int Hungarian()
    {
        int cnt = 0;
        for (int i = 1; i <= M; ++i)
        {
            memset(vis, 0, sizeof(vis)); //重置vis数组
            if (match(i))
                cnt++;
        }
        return cnt;
    }
    

    OK

  • 相关阅读:
    10055
    国外程序员推荐:每个程序员都应该读的非编程书
    Volume 0. Getting Started
    如何成为一名 Google 软件工程师?【Google招聘信息】作者: 丁鑫哲
    毕设-家校通
    如何快速创建数据库连接字符串
    LeetCode day13
    LeetCode day12
    LeetCode day11
    LeetCode day10 Called it
  • 原文地址:https://www.cnblogs.com/savennist/p/13429356.html
Copyright © 2011-2022 走看看