• 二分图的最大匹配


    3个重要结论:

    最小点覆盖数: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数
    最小路径覆盖=最小路径覆盖=|N|-最大匹配数
    用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。
    二分图最大独立集=顶点数-二分图最大匹配
    在N个点的图G中选出m个点,使这m个点两两之间没有边,求m最大值。
    如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = N - 最大匹配数。

    例题:

    http://poj.org/problem?id=1469  COURSES

    有了匈牙利算法的基础,该题就是一道非常简单的题目了:该题给出P门课程,N个学生,问能否从中选出P个学生,使每个学生上不同的课,且每个课程有一个学生。典型的二分图匹配的问题,我们只要计算最大二分图匹配数,如果和课程数相同就输出YES,否则输出NO。

    //poj_1469  
    /*==================================================* 
    | 二分图匹配(匈牙利算法DFS 实现) 
    | INIT: g[][]邻接矩阵; 
    | 优点:实现简洁容易理解,适用于稠密图,DFS找增广路快。 
    | 找一条增广路的复杂度为O(E),最多找V条增广路,故时间复杂度为O(VE) 
    ==================================================*/  
    #include<stdio.h>  
    #include<memory.h>  
      
    bool g[110][310]; //邻接矩阵,true代表有边相连  
    bool flag,visit[310];    //记录V2中的某个点是否被搜索过  
    int match[310];   //记录与V2中的点匹配的点的编号  
    int p,n;   //二分图中左边、右边集合中顶点的数目   
      
    // 匈牙利算法  
    bool dfs(int u)  
    {  
        for (int i = 1; i <= n; ++i)  
        {  
            if (g[u][i] && !visit[i])   //如果节点i与u相邻并且未被查找过  
            {  
                visit[i] = true;   //标记i为已查找过  
                if (match[i] == -1 || dfs(match[i]))   //如果i未在前一个匹配M中,或者i在匹配M中,但是从与i相邻的节点出发可以有增广路径  
                {  
                    match[i] = u;  //记录查找成功记录,更新匹配M(即“取反”)  
                    return true;   //返回查找成功  
                }  
            }  
        }  
        return false;  
    }  
      
    int main(void)  
    {  
        int i,j,k,t,v,ans;  
        scanf("%d",&t);  
        while (t--)  
        {  
              scanf("%d %d", &p, &n);  
              for (i = 1; i <= p; i++)  
              {  
                  for (j = 1; j <= n; j++)  
                      g[i][j] = false;  
              }  
              for (i = 1; i <= n; i++)  
                  match[i] = -1;  
              flag = true;  
              for (i = 1; i <= p; i++)  
              {  
                  scanf("%d",&k);  
                  if (k == 0)  
                     flag = false;  
                  while (k--)  
                  {  
                        scanf("%d",&v);  
                        g[i][v]  = true;  
                  }  
              }  
              if (flag)  
              {  
                   ans = 0;  
                   for (i = 1; i <= p; i++)  
                   {  
                       memset(visit,false,sizeof(visit));   //清空上次搜索时的标记  
                       if( dfs(i) )    //从节点i尝试扩展  
                           ans++;  
                   }  
                   if (ans == p)  
                       puts("YES");  
                   else  
                       puts("NO");  
              }   
              else  
                  puts("NO");  
        }  
          
        return 0;  
    }  
  • 相关阅读:
    [WPF]WPF3.5 SP1 TreeView的Bug
    2010年自我总结
    LINQ to SQL 异常:SQL Server does not handle comparison of NText, Text, Xml, or Image data types
    [翻译] javascript缩进
    【转】疑难解答:调试 Windows 服务
    【翻译】MSDN文档对类DefaultValueAttribute的描述有些混淆
    二叉排序树——算法系列
    索引查找——算法系列
    android软电话开发预备知识
    adb server is out of date.killing
  • 原文地址:https://www.cnblogs.com/yuanbo123/p/6770565.html
Copyright © 2020-2023  润新知