图论2——二分图与匈牙利算法

一般情况下,我们用的都是简单图。带权图,无向图;还有各种算法,像Floyd,SPFA,Dijkstra……

但是,在我们需要进行一些匹配问题的时候,我们就不能够只是用简单图了,不然最终可能会收获TLE(超时)。

这个时候,我们就要让二分图出场了!

1、二分图的应用

我们举一个最简单的例子。有N名男运动员和M名女运动员要组成尽可能的多的混双配对,其中有一些不能够配对,请问如何处理?

这时候,大家就可能比较头疼——没有什么思路。各种数据结构似乎也都无能为力,组合数论看起来可以,实际上也算不出来,更不会有人想到这是图论。

然而这就是一道二分图模板题。

【题目大意】

有N名男运动员和M名女运动员要组成尽可能的多的混双配对,其中有一些不能够配对,请问如何处理?

【输入格式】

第一行 输入三个整数,N,M,K,,表示男运动员的个数,女运动员的个数,以及可匹配对数。

以下K行,每行两个整数a,b,表示男运动员a,b可以配对比赛。

【输出格式】

只有一个整数,为最多的混双配对。

【输入样例】

5 4 14

1 1

1 2

2 3

3 2

4 2

4 3

4 4

5 4

5 2

5 3

3 3

2 4

1 3

2 1

【输出样例】

4

【算法分析】

我们之前已经分析过它是一道图论题,但是怎么建图呢?

如果我们把每一个运动员看做图的顶点V,将每一对可配对的连接,则上面的样例可以表示为下图(无向图)。

那么你会做了吗?

其实上面这张图就是一张二分图。二分图的定义大致如下。

图G=[V,E]是一个无向图,顶点集合V分为X和Y两部分,G中的每一条边一定一个端点在X,一个端点在Y。

所以,二分图也可以记为G=[X,Y,E]。

我们也知道,有一种东西叫做完全二叉树,那么有没有完全二分图呢?

当然有。当X中的任意结点都与Y中的地所有节点连接时,它就是一个完全二分图(因为是无向图,所以亦可为Y中的节点与X中所有节点连接)。

【定理】

当且仅当无向图G的每一个回路长度均为偶数时,该图才是一个二分图。(包括无回路的情况)

题目中的求尽可能多的混双配对,其实也就是求二分图的最大匹配。

2、二分图的最大匹配

要解决二分图的最大匹配问题,我们有几种算法,例如网络流。但是,今天我要讲的,是Edmonds在1965年提出的匈牙利算法(Hungary Algorithm)。

首先,我们来了解一些名词。在这里,我们暂时设M为一张二分图中可能出现的最大匹配方案。

交错轨

设P是二分图中的一条路径,如果该路径任意两条相邻边一条在M内(是最大方案的一部分),另一条不在M内(不是最大方案的一部分),那么它就是一条交错轨。

特别的,如果该路径中只有一条边,那么他一定是一条 交错轨,不论在M内外。

可增广轨

我们再定义一个点“是否有连接着最大匹配方案里的边”为这个点是否被“盖住”。如果交错轨的两个定点都是没有被“盖住”的,那么他就是一个可增广轨。

为什么要寻找可增广轨呢?因为,如果你在寻找最大匹配方案时能够找到一个可增广轨的话,那么最大匹配方案就可以增加到当前方案匹配数+1。

讲了这么多,现在开始讲一讲匈牙利算法。

他其实就是最开始把最大匹配方案M置为空集,然后反复寻找增广路径,知道没有为止,就这么简单。

增广路径的找法,就是DFS或BFS。在针对稠密图时建议DFS,反之则为BFS。

下面,给出DFS的Cpp参考代码。

#include<cstdio>
#include<cstring>
const int MAX=1001;
int n,m,k;
int link[MAX];
bool vis[MAX];
bool map[MAX][MAX];
bool dfs(int a)
{
    for(int i=1;i<=m;i++)
        if(map[a][i]==1&&!vis[i])
        {
            vis[i]=1;
            if(!link[i]||dfs(link[i]))
            {
                link[i]=a;
                return 1;
            }
        }
    return 0;
}
int main()
{
    int a,b,ans=0;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;i++)
    {
        scanf("%d%d",&a,&b);
        map[a][b]=1;
    }
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof(vis));
        if(dfs(i))
            ans++;
    }
    printf("%d\n",ans);
    return 0;
}

关于BFS,这里同样给出示范性的Cpp代码。

#include<cstdio>
#include<cstring>
const int MAX=1001;

struct link
{
    int data;
    link *nxt;
    link(int=0);
};
link::link(int n)//类继承
{
    data=n;
    nxt=NULL;
}
int n,m,k,ans=0;
int res[MAX];
bool state[MAX];
link *head[MAX],*lst[MAX];

bool bfs(const int n)
{
    link* t=head[n];
    while(t!=NULL)
    {
        if(!state[t->data])
        {
            state[t->data]=1;
            if(!res[t->data]||bfs(res[t->data]))
            {
                res[t->data]=n;
                return 1;
            }
        }
        t=t->nxt;
    }
    return 0;
}
int main()
{
    int a,b;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<k;i++)
    {
        scanf("%d%d",&a,&b);
        if(lst[a]==NULL)
            lst[a]=head[a]=new link(b);
        else
            lst[a]=lst[a]->nxt=new link(b);
    }
    for(int i=1;i<=n;i++)
    {
        memset(state,0,sizeof(state));
        if(bfs(i))
            ans++;
    }
    printf("%d\n",ans);
    return 0;
}

本篇博客到这里就结束了,希望大家能满意,然后点个赞,谢谢!

时间: 2024-10-04 23:55:22

图论2——二分图与匈牙利算法的相关文章

POJ1274:The Perfect Stall(二分图最大匹配 匈牙利算法)

The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17895   Accepted: 8143 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering pr

USACO 4.2 The Perfect Stall(二分图匹配匈牙利算法)

The Perfect StallHal Burch Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering problems, all the stalls in the new barn are different. For the first week, Farmer John r

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

Kingdom of Obsession Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 49    Accepted Submission(s): 14 Problem Description There is a kindom of obsession, so people in this kingdom do things very

Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)

解题报告 二分图第一题. 题目描述: 为了参加即将召开的会议,A国派出M位代表,B国派出N位代表,(N,M<=1000) 会议召开前,选出K队代表,每对代表必须一个是A国的,一个是B国的; 要求每一个代表要与另一方的一个代表联系,除了可以直接联系,也可以电话联系,求电话联系最少 思路: 电话联系最少就要使直接联系最大,又是一一匹配关系,就是二分图的最大匹配. 下面是匈牙利算法. #include <cstdio> #include <cstring> #include <

UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法

二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> u

POJ1274 The Perfect Stall 二分图,匈牙利算法

N头牛,M个畜栏,每头牛只喜欢其中的某几个畜栏,但是一个畜栏只能有一只牛拥有,问最多可以有多少只牛拥有畜栏. 典型的指派型问题,用二分图匹配来做,求最大二分图匹配可以用最大流算法,也可以用匈牙利算法,这里使用匈牙利算法. #include <stdlib.h> #include <stdio.h> #include <vector> #include <math.h> #include <string.h> #include <string

过山车(二分图_匈牙利算法)

Description RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐.但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner.考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿

HDU1507 Uncle Tom&#39;s Inherited Land* 二分图匹配 匈牙利算法 黑白染色

原文链接http://www.cnblogs.com/zhouzhendong/p/8254062.html 题目传送门 - HDU1507 题意概括 有一个n*m的棋盘,有些点是废的. 现在让你用1*2的矩形覆盖所有的不废的点,并且不重叠,问最多可以覆盖多少个1*2的矩形,输出方案,有SPJ. 输入描述: 多组数据,每组首先两个数n,m(如果n和m为0,则结束程序) 然后给出k 然后给出k个二元组(x,y)表示废点的坐标. 题解 按照前两片博文的算法已经不行了,因为方案不对了. 所以我们要进行

图论-二分图匹配-匈牙利算法

有关概念: 二分图:图G中的点集可以分为两个互不相交的子集,且G中的每条边连接的两个点分别属于这两个子集 二分图匹配:二分图G的子图M中每个结点上只连一条边,则称M为一个匹配 极大匹配:无法再向二分图中加边且满足匹配条件的匹配 最大匹配:所有极大匹配中边数最多的一个 增广路:若P为图G上连接两个未匹配结点的路径,且已匹配边和未匹配边在P上交替出现,则称P为相对于M的一条增广路 匈牙利算法即用来求二分图的极大匹配 思路: 在图G中找出增广路P,对P上每一条边取反(即已匹配边改为未匹配边,未匹配边改