zoukankan      html  css  js  c++  java
  • 寒假Day9:二分图的判断+匈牙利算法

    二分图匹配相关概念

    给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配

    极大匹配是指在当前已完成的匹配下,无法再通过增加未完成匹配的边的方式来增加匹配的边数。

    最大匹配是所有极大匹配当中边数最大的一个匹配。选择这样的边数最大的子集称为图的最大匹配问题。

    如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。

    求解算法:求二分图匹配可以用最大流(Maximal Flow)或者匈牙利算法。

    注意:完全匹配一定是极大匹配,但是极大匹配不一定是完全匹配。

    交替路:从一个未匹配的点出发,依次经过未匹配边、匹配边、未匹配边....这样的路叫做交替路。

    增广路:从一个未匹配的点出发,走交替路,到达了一个未匹配过的点,这条路叫做增广路。

    看下图,其中1、4、5、7是已经匹配的点,1->5,4->7是已经匹配的边,那么我们从8开始出发,8->4->7->1->5->2这条路就是一条增广路。


    二分图的判断

     对于二分图的问题我们首先要判断一个图它是不是二分图。

    对于二分图的判断方法最常见的是染色法(对每一个点进行染色操作,我们只用黑白两种颜色,问能不能使所有的点都染上了色,而且相邻两个点的颜色不同,如果可以那么这个图就是一个二分图)。

    对于判断是否是一个二分图的方法可以用dfsbfs两种方式去实现。

    bfs判断二分图:

     1 bool bfs()//用bfs 判断一幅图是否是二分图
     2 {
     3     memset(col,0,sizeof(col));
     4     //染色后的状态只有1和-1
     5     //所以染色的初始状态为全部清空为0
     6     queue<int> Q;
     7     Q.push(1);//先让第一个点入队
     8     col[1]=1;//给第一个点染色为1
     9     while(!Q.empty())
    10     {
    11         int p=Q.front();
    12         Q.pop();
    13         for(int i=0; i<v[p].size(); i++)
    14         {
    15             //找与第一个点相邻的点
    16             int x=v[p][i];
    17             if(col[x]==0)//如果未被染色
    18             {
    19                 col[x]=-col[p];//就染成与当前点相反的颜色
    20                 Q.push(x);
    21             }
    22             else//如果已经被染色了且和当前节点染色相同,则确定不是二分图
    23             {
    24                 if(col[p]==col[x])
    25                     return 0;
    26             }
    27         }
    28     }
    29     return 1;
    30 }

    匈牙利算法

     时间复杂度:O(n*m)

     匈牙利算法模板:

     1 bool dfs(int x)
     2 {
     3     for(int i=0; i<v[x].size(); i++)
     4     {
     5         int s=v[x][i];
     6         if(book[s]==0) // 判断是否标记过,没有被标记进行下一步
     7         {
     8             book[s]=1;
     9             if(f[s]==-1||dfs(f[s]))  // 如果没有被匹配过且能和其他的点进行匹配
    10             {
    11                 f[s]=x;
    12                 return 1;
    13             }
    14         }
    15     } 
    16     return 0;
    17 }

    补充:

    • 匈牙利算法得到的最大匹配并不是唯一的,预设匹配边、或者匹配顺序不同等,都可能会导致有多种最大匹配情况,所以有一种替代KM算法的想法是,我们只需要用匈牙利算法找到所有的最大匹配,比较每个最大匹配的权重,再选出最大权重的最优匹配即可得到更贴近真实情况的匹配结果。但这种方法时间复杂度较高,会随着目标数越来越多,消耗的时间大大增加,实际使用中并不推荐。 
    • 匈牙利算法是最简单最常见的求最大匹配数的算法,但是它的时间复杂度是O(n*m),对于一般的题来说最多有500个点,所以匈牙利是最好的做法。
    • 假如遇到点数更多的话,可以使用Hopcroft-Karp算法,它的时间复杂度是O(n^(1/2) * m)。
    • 以后碰到更深的题目再去学习一下HK算法KM算法(带权二分图的最优匹配问题)匈牙利算法求二分图多重匹配

    小知识点:

    • Have all the workers punched in yet?
      所有工人上班都打卡了吗?   punch in 打卡 ~on time  
    • abs是求一个整数的绝对值,fabs是求一个实数的绝对值
    • 数组开小了不会显示RE,会提示超时

    可参考博客:

    https://blog.csdn.net/dark_scope/article/details/8880547

  • 相关阅读:
    全面理解面向对象的 JavaScript
    账号
    移动端 前端框架 amaze ui
    javascript 精典案例分析一览
    前端事件系统(一)
    周总结12
    周总结11
    相比较于其他的同类软件
    团队冲刺第十五天
    团队冲刺第十四天
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12228048.html
Copyright © 2011-2022 走看看