zoukankan      html  css  js  c++  java
  • 题解 P3386 【【模板】二分图匹配】

    二分图匹配的常用算法有匈牙利算法和Dinic算法,这里只讨论前者。


    所谓二分图,就是指一类能够被分成两半的图,其中每一半的点都没有任何边连接。

    而二分图的匹配,就是指二分图的一个子图中任意两条边都没有公共点。(这个子图就是一个匹配)

    本题求的是最大匹配数,顾名思义,就是匹配中边数最大为多少。


    匈牙利算法的本质是贪心。我们每一次都找一条增广路,然后再取反寻找比当前匹配更大的匹配。没有增广路就结束。

    百度百科是这样定义增广路的:

    若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径(举例来说,有A、B集合,增广路由A中一个点通向B中一个点,再由B中这个点通向A中一个点……交替进行)。
    


    实现

    我们使用DFS实现匈牙利算法。

    inline bool dfs(int u){
        for(int v=1;v<=m;v++)
            if(t[u][v]&&!vis[v]){
                vis[v]=1;
                if(cy[v]==-1||dfs(cy[v])){
                    cx[u]=v;cy[v]=u;
                    return 1;
                }
            }
        return 0;
    }
    

    这段代码寻找从u出发的增广路。

    首先我们先枚举与u有连接的所有节点。

    然后如果未访问就进去逛一逛。

    如果发现这个节点还没有被匹配或者说存在从它出发的增广路,那就跳进去。回溯时返回true,表示存在从u出发的增广路。

    如果逛了一圈一个节点都不行,那就返回false,因为没有从u出发的增广路。

    for(int i=0;i<=nx;i++) 
    	if(cx[i]==-1){ 
        	memset(visit,false,sizeof(visit)) ; 
            ans += dfs(i); 
        }
    

    在主程序中我们过一遍所有点,如果当前未匹配就dfs一下,然后根据dfs返回值更新答案。

  • 相关阅读:
    [ERROR] Terminal initialization failed; falling back to unsupported
    设计模式原则
    设计模式:概述
    INFO Dispatcher:42
    Exception occurred during processing request: id to load is required for loading
    Java编程基础篇第六章
    Spring (一)(未完~~~
    Spring MVC处理过程理解(一)
    Spring MVC源码解析(二)
    MyBatis拦截器(一)
  • 原文地址:https://www.cnblogs.com/ilverene/p/9850582.html
Copyright © 2011-2022 走看看