前言:居然三天没有更新了。。我的效率实在太低,每天都用各种各样的理由拖延,太差了!昨天的contest依旧不能让人满意,解出的三题都是队友A的,我又卖了一次萌。。好吧废话不多说,今天我要纪录的是二分图相关的一些算法及题目,希望通过这种方式加深自己对二分图的理解(其实还没完全理解。。)

二分图的最大匹配

二分图最大匹配的题目最重要的是建模,模型建出来后,通过各种定理转化成二分图的最大匹配来做,还是很方便的,下面是几个重要定理:

  • 二分图的最小点集覆盖=二分图的最大匹配
  • 有向图的最小路径覆盖=N-转化后二分图的最大匹配
  • 二分图的最大独立集=二分图的最小边覆盖=N-二分图的最大匹配
  • 二分图的最大团=补图的最大独立集

匈牙利算法模板:

 #include<stdio.h>
#include<string.h>
  
bool g[][];
int n,m,ans;
bool b[];
int link[];
  
bool init()
{
        int _x,_y;
        memset(g,,sizeof(g));
        memset(link,,sizeof(link));
        ans=;
        if(scanf("%d%d",&n,&m)==EOF)return false;
        for(int i=;i<=n;i++)
        {
                scanf("%d",&_x);
                for(int j=;j<_x;j++)
                {
                        scanf("%d",&_y);
                        g[ i ][_y]=true;
                }
        }
        return true;
}
  
bool find(int a)
{
        for(int i=;i<=m;i++)
        {
                if(g[a][ i ]==&&!b[ i ])
                {
                        b[ i ]=true;
                        if(link[ i ]==||find(link[ i ]))
                        {
                                link[ i ]=a;
                                return true;
                        }
                }
        }
        return false;
}
  
int main()
{
        while(init())
        {
                for(int i=;i<=n;i++)
                {
                        memset(b,,sizeof(b));
                        if(find(i))ans++;
                }
                printf("%d\n",ans);
        }
}

稳定婚姻系统

稳定婚姻系统,举一个很简单易懂的例子:有N个男生和M个女生要配对成情侣,每个男生都有一个按照喜欢程度由高到低的心仪女生的列表,每个女生对男生同样。一个稳定婚姻系统,是指对任意一对情侣(a,b),不存在另一对情侣(c,d),使得a更喜欢d,d也更喜欢a,同理,不存在另一对情侣(e,f),使得e更喜欢b,b也更喜欢e。

求解这个问题可以用一个专有的算法,延迟认可算法,其核心就是让每个男生按自己喜欢的顺序逐个向女生表白,例如leokan向一个女生求爱,这个过程中,若这个女生没有男朋友,那么这个女生就暂时成为leokan的女朋友,或这个女生喜欢她现有男朋友的程度没有喜欢leokan高,这个女生也暂时成为leokan的女朋友,而她原有的男朋友则再将就找下一个次喜欢的女生来当女朋友。(摘自leokan百度空间)

下面的算法框架由Gale和Shapley于1962年提出,在此膜拜一下(摘自维基百科)

函数 稳定婚姻 {
初始所有 m

 M 与 w 

 W 为 单身
     

 单身 男子 m {
       w = m所有可考虑的女子中排名最高的
w 是 单身
撮合 (m, w)
否则 有些夫妇 (m', w) 存在
w 喜欢 m 更于 m'
(m, w) 为 夫妇
m' 为 单身
否则
(m', w) 仍为 夫妇
}
}

稳定婚姻系统的应用:任务分配、大学联合招生

二分图最大/最小权匹配

什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和最大或最小。而二分图的最佳匹配则一定为完备匹配,在此基础上,才要求匹配的边权值之和最大或最小。二分图的带权匹配与最佳匹配不等价,也不互相包含。(摘自BYVoid博客

首先介绍一下KM算法:

KM算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题的。设顶点Xi的顶标为A[i],顶点Yi的顶标为B [i],顶点Xi与Yj之间的边权为w[i,j]。在算法执行过程中的任一时刻,对于任一条边(i,j),A[i]+B[j]>=w[i,j]始终 成立。KM算法的正确性基于以下定理:
若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。
这个定理是显然的。因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和。所以相等子图的完备匹配一定是二分图的最大权匹配。
初始时为了使A[i]+B[j]>=w[i,j]恒成立,令A[i]为所有与顶点Xi关联的边的最大权,B[j]=0。如果当前的相等子图没有完备匹配,就按下面的方法修改顶标以使扩大相等子图,直到相等子图具有完备匹配为止。
我们求当前相等子图的完备匹配失败了,是因为对于某个X顶点,我们找不到一条从它出发的交错路。这时我们获得了一棵交错树,它的叶子结点全部是X顶点。现在我们把交错树中X顶点的顶标全都减小某个值d,Y顶点的顶标全都增加同一个值d,那么我们会发现:
两端都在交错树中的边(i,j),A[i]+B[j]的值没有变化。也就是说,它原来属于相等子图,现在仍属于相等子图。
两端都不在交错树中的边(i,j),A[i]和B[j]都没有变化。也就是说,它原来属于(或不属于)相等子图,现在仍属于(或不属于)相等子图。
X端不在交错树中,Y端在交错树中的边(i,j),它的A[i]+B[j]的值有所增大。它原来不属于相等子图,现在仍不属于相等子图。
X端在交错树中,Y端不在交错树中的边(i,j),它的A[i]+B[j]的值有所减小。也就说,它原来不属于相等子图,现在可能进入了相等子图,因而使相等子图得到了扩大。
现在的问题就是求d值了。为了使A[i]+B[j]>=w[i,j]始终成立,且至少有一条边进入相等子图,d应该等于min{A[i]+B[j]-w[i,j]|Xi在交错树中,Yi不在交错树中}。
以上就是KM算法的基本思路。但是朴素的实现方法,时间复杂度为O(n4)——需要找O(n)次增广路,每次增广最多需要修改O(n)次顶 标,每次修改顶标时由于要枚举边来求d值,复杂度为O(n2)。实际上KM算法的复杂度是可以做到O(n3)的。我们给每个Y顶点一个“松弛量”函数 slack,每次开始找增广路时初始化为无穷大。在寻找增广路的过程中,检查边(i,j)时,如果它不在相等子图中,则让slack[j]变成原值与A [i]+B[j]-w[i,j]的较小值。这样,在修改顶标时,取所有不在交错树中的Y顶点的slack值中的最小值作为d值即可。但还要注意一点:修改 顶标后,要把所有的slack值都减去d。(摘自CrazyAC

评价:反正KM算法我一开始看了好几遍都不是很懂,现在还没有特别明白,不过脑子里大概有这么一个感觉:最外层for循环n次,保证能构成一个完备匹配,内层不断修改顶标,使得不断有边加入能构成一条新的增广路,每找到一条就跳出while循环,执行下一轮循环。

KM算法就是用来解决二分图最佳匹配问题的,时间复杂度是O(N^3)。BYVoid大牛根据不同的情况对KM算法进行了转化:

[KM算法的几种转化]

  • KM算法是求最大权完备匹配,如果要求最小权完备匹配怎么办?方法很简单,只需将所有的边权值取其相反数,求最大权完备匹配,匹配的值再取相反数即可。
  • KM算法的运行要求是必须存在一个完备匹配,如果求一个最大权匹配(不一定完备)该如何办?依然很简单,把不存在的边权值赋为0。
  • KM算法求得的最大权匹配是边权值和最大,如果我想要边权之积最大,又怎样转化?还是不难办到,每条边权取自然对数,然后求最大和权匹配,求得的结果a再算出e^a就是最大积匹配。至于精度问题则没有更好的办法了。

KM算法模板:(题目来源:HDU2255)

 //
//  HDU2255.cpp
//  POJ
//
//  Created by TimmyXu on 13-8-4.
//  Copyright (c) 2013年 TimmyXu. All rights reserved.
//
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
 
using namespace std;
 
const int maxn = + ;
 
int l[maxn],r[maxn],match[maxn],g[maxn][maxn],n,ans,d;
bool lv[maxn],rv[maxn];
 
void Init()
{
    memset(g,,sizeof(g));
    for (int i = ;i <= n;i++)
        for (int j = ;j <= n;j++)
            scanf("%d",&g[i][j]);
    for (int i = ;i <= n;i++)
        l[i] = INT_MIN;
    memset(r,,sizeof(r));
    memset(match,,sizeof(match));
}
 
bool check(int x)
{
    lv[x] = true;
    for (int y = ;y <= n;y++)
        if (!rv[y])
        {
            int t = l[x]+r[y]-g[x][y];
            if (t == )
            {
                rv[y] = true;
                if (match[y] == || check(match[y]))
                {
                    match[y] = x;
                    return true;
                }
            }
            else d = min(d,t);
        }
    return false;
}
 
void KM()
{
    for (int i = ;i <= n;i++)
        for (int j = ;j <= n;j++)
            l[i] = max(l[i],g[i][j]);
    for (int i = ;i <= n;i++)
        while(true)
        {
            memset(lv,false,sizeof(lv));
            memset(rv,false,sizeof(rv));
            d = INT_MAX;
            if (check(i)) break;
            for (int j = ;j <= n;j++)
            {
                if (lv[j]) l[j]-=d;
                if (rv[j]) r[j]+=d;
            }
        }
    ans = ;
    for (int i = ;i <= n;i++)
        ans += g[match[i]][i];
    printf("%d\n",ans);
}
 
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        Init();
        KM();
    }
}

二分图最大权问题还可以用费用流来做,关于网络流相关内容我准备今天下午开始研究,作为这几天的研究重点。

总结:关于二分图的题目我做的比较少,因此建模方面的能力还比较欠缺,要在平时过程慢慢积累,不能偷懒,要勤于刷题。下面网络流专题是一座大山,要投入足够多的精力,储备足够多的智商才能搞定吧。

【ACM/ICPC2013】二分图匹配专题的更多相关文章

  1. HDU 3081:Marriage Match II(二分图匹配+并查集)

    http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也 ...

  2. HDU 1083 网络流之二分图匹配

    http://acm.hdu.edu.cn/showproblem.php?pid=1083 二分图匹配用得很多 这道题只需要简化的二分匹配 #include<iostream> #inc ...

  3. hdu 5727 Necklace dfs+二分图匹配

    Necklace/center> 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5727 Description SJX has 2*N mag ...

  4. HDU5090--Game with Pearls 二分图匹配 (匈牙利算法)

    题意:给N个容器,每个容器里有一定数目的珍珠,现在Jerry开始在管子上面再放一些珍珠,放上的珍珠数必须是K的倍数,可以不放.最后将容器排序,如果可以做到第i个容器上面有i个珍珠,则Jerry胜出,反 ...

  5. HDU 5943 Kingdom of Obsession 【二分图匹配 匈牙利算法】 (2016年中国大学生程序设计竞赛(杭州))

    Kingdom of Obsession Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  6. HDU 5727 Necklace(二分图匹配)

    [题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5727 [题目大意] 现在有n颗阴珠子和n颗阳珠子,将它们阴阳相间圆排列构成一个环,已知有些阴珠子和阳 ...

  7. POJ 2289 Jamie's Contact Groups / UVA 1345 Jamie's Contact Groups / ZOJ 2399 Jamie's Contact Groups / HDU 1699 Jamie's Contact Groups / SCU 1996 Jamie's Contact Groups (二分,二分图匹配)

    POJ 2289 Jamie's Contact Groups / UVA 1345 Jamie's Contact Groups / ZOJ 2399 Jamie's Contact Groups ...

  8. FZU - 2039 Pets (二分图匹配 2011年全国大学生程序设计邀请赛(福州))

    Description Are you interested in pets? There is a very famous pets shop in the center of the ACM ci ...

  9. HDU4685:Prince and Princess(二分图匹配+tarjan)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

随机推荐

  1. .NET异步操作学习之一:Async/Await中异常的处理

    以前的异常处理,习惯了过程式的把出现的异常全部捕捉一遍,然后再进行处理.Async/Await关键字出来之后的确简化了异步编程,但也带来了一些问题.接下来自己将对这对关键字进行学习.然后把研究结果放在 ...

  2. node.js操作mongoDB数据库

    链接数据库: var mongo=require("mongodb"); var host="localhost"; var port=mongo.Connec ...

  3. CentOS 6.4 使用YUM 安装MySQL5.5

    1.首先需要下载Yum的支持包: http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm 2.下载完成后将Yum库导入到你的 ...

  4. OS概论1

    1.设计现代OS的主要目标是什么? 在计算机上配置操作系统,其主要目标是:方便性,有效性,可扩充性,开放性. 一个没有OS的操作系统,就必须用机器语言书写程序,如果在计算机上配置了OS,系统便可以使用 ...

  5. C# 获取随机可用端口号

    TCP与UDP段结构中端口地址都是16比特,可以有在0---65535范围内的端口号.对于这65536个端口号有以下的使用规定: (1)端口号小于256的定义为常用端口,服务器一般都是通过常用端口号来 ...

  6. bzoj 2251: [2010Beijing Wc]外星联络 后缀数组

    2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 424  Solved: 232[Submit][ ...

  7. Logstash同步Oracle数据到ElasticSearch

    最近在项目上应用到了ElasticSearch和Logstash,在此主要记录了Logstash-input-jdbc同步Oracle数据库到ElasticSearch的主要步骤,本文是对环境进行简单 ...

  8. keybd_event函数用法

    转自不用winio,直接达到驱动级模拟键盘效果的keybd_event函数用法 键盘模拟技术是在编写游戏外挂时经常使用的技术.但是由于很多游戏采用了directinput的方式,使得发送的一般键盘消息 ...

  9. ArrayList与Vector、HashMap与HashTable

    摘自api: 1.ArrayList与Vector: 原文:This class(ArrayList) is roughly equivalent to Vector, except that it ...

  10. HDU 1394 Minimum Inversion Number(线段树的单点更新)

    点我看题目 题意 :给你一个数列,a1,a2,a3,a4.......an,然后可以求出逆序数,再把a1放到an后,可以得到一个新的逆序数,再把a2放到a1后边,,,,,,,依次下去,输出最小的那个逆 ...