• 匈牙利算法


    匈牙利算法 \color{red}{\huge{匈牙利算法}} 匈牙利算法

    定义与最大匹配

    匈牙利算法就是用来 二分图的最大匹配问题 \color{blue}{二分图的最大匹配问题} 二分图的最大匹配问题。该算法是匈牙利的一个数学家 E d m o n d s Edmonds Edmonds提出的,所以被后人称之为匈牙利算法。

    最大匹配 . . ? \color{orange}{\huge{最大匹配..?}} 最大匹配..
    通俗一点来讲就是,对于一个二分图,①.所有的边都是两个点集合之间的。②. 一个边所连的两个点只能拥有当前这条边,不能够在连接其他的边了 \color{red}{一个边所连的两个点只能拥有当前这条边,不能够在连接其他的边了} 一个边所连的两个点只能拥有当前这条边,不能够在连接其他的边了
    满足这两个条件之后,求这样的边的条数。
    在这里插入图片描述

    算法流程

    把二分图左右两侧的点的集合分成 n 1 n_{1} n1 n 2 n_{2} n2,执行算法流程:

    for(每一个n1中的点)
    {
        for(遍历到当前n1中的点n1'所相连的n2中的点n2')
        {
            if(n2'现有的连接可以调整)
            {
                match[n2'] = n1';
                res++;          //匹配数            
                匹配成功返回
            }
            else 
                匹配失败
        }
    }
    return res;
    

    样例模拟

    在这里插入图片描述

    解释:一开始黑 1 1 1连接了红 1 1 1和红 2 2 2,那么黑 1 1 1就已经默认匹配好了对方的红 1 1 1,变为灰线。之后黑 2 2 2进行匹配,黑 2 2 2优先进行与红 1 1 1进行匹配,发现红 1 1 1已经有了匹配,于是溯源到黑 1 1 1,看黑 1 1 1可不可以调整一下匹配,使得黑 2 2 2与红 1 1 1进行匹配成功,答案是可以的。黑 1 1 1还可以与红 2 2 2进行匹配,于是调整一下,最后优化成为了黑 1 1 1匹配红 2 2 2,黑 2 2 2匹配红 1 1 1。优化完成。

    算法实现

    h [ N ] , e [ M ] , n e [ M ] , i d x h[N] , e[M] , ne[M] , idx h[N],e[M],ne[M],idx:邻接表组件,老生常谈。
    m a t c h [ N ] match[N] match[N]:匹配函数, m a t c h [ j ] = a match[j] = a match[j]=a表示右侧 j j j对应的匹配是左侧的 a a a点。
    s t [ N ] st[N] st[N]:标志右侧的点有没有对应左侧的匹配成功。

    K e y : F i n d ( 寻找左侧点的一个右侧匹配, 返回是否成功 ) \color{red}{\huge{Key:}}Find(寻找左侧点的一个右侧匹配,\color{blue}{返回是否成功}) Key:Find(寻找左侧点的一个右侧匹配,返回是否成功)

    bool Find(int x)        //输入的参数是左侧的点
    {
        for(int i = h[x] ; i != -1 ; i = ne[i])     //遍历左侧点相邻的所有右侧点
        {
            int j = e[i];
            
            if(!st[j])              //如果右侧点没有确定匹配
            {
                st[j] = true;       //置成已经匹配成功的状态
                if(match[j] == 0 || find(match[j])  
                //如果这个右侧点没有匹配或者对应之前左侧点的匹配能够调整
                {
                    match[j] = x;       //这个右侧点的匹配置为当前的左侧点
                    return ture;
                }
            }
        }
        
        return false;
    }
    

    完整代码

    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 510 , M = 100010;
    
    int n1,n2,m;
    int h[N],e[M],ne[M],idx;
    int match[N];
    bool st[N];
    
    void add(int a,int b)
    {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }
    
    bool find(int x)
    {
        for(int i = h[x] ; i != -1 ; i = ne[i])
        {
            int j = e[i];
            if(!st[j])
            {
                st[j] = true;
                if(match[j] == 0 || find(match[j]))
                {
                    match[j] = x;
                    return true;
                }
            }
        }
        
        return false;
    }
    
    
    int main ()
    {
        cin >>n1 >> n2 >> m;
        
        memset(h,-1,sizeof(h));
        
        while(m--)
        {
            int a,b;
            
            cin >> a >>b;
            
            add(a,b);
        }
        
        int res = 0;
        
        for(int i = 1 ; i <= n1 ; i++)
        {
            memset(st,false,sizeof(st));
            if(find(i))
                res++;
        }
        
        cout << res << endl;
        
        return 0;
    }
    
  • 相关阅读:
    如何求和第K大(小)的子序列
    AI大模型使用(七)-模型微调与流式生成
    vscode + gdb +gdbserver 远程调试Pg源码
    Redis 缓存数据库
    社会网络分析软件
    DHCP自动分配IP原理
    国内常用的代理ip形式数据中心代理ip和静态住宅代理IP有什么区别
    RabbitMq中的warren模式和shovel模式
    图的应用4.0-----关键路径(AOE网)
    强烈推荐:2024 年12款 Visual Studio 亲测、好用、优秀的工具,AI插件等
  • 原文地址:https://blog.csdn.net/qq_51542797/article/details/127121438