二分图和普通图的匹配(匈牙利和带花树算法)

二分图的定义:
设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。
啊这什么破定义 ,上图上图:
在这里插入图片描述

看图就很清楚了,将整张图的点划分为两个集合,集合内部的点互不连接,这样的图就叫二分图。而不满足这样的条件的就叫普通图。
像这样:
在这里插入图片描述

那什么叫匹配呢?
给定一个二分图G,在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,则称M是一个匹配.
什么玩意完全让人理解不了嘛。 上图:
在这里插入图片描述

被绿线圈中的点就是属于两两匹配的点(画的好难看
被匹配的两个点必须是有某条边直接相连。
而求出二分图中最大匹配数(就是最多有多少对点匹配起来了),就叫二分图的最大匹配问题
由上图,这个图显然未达最大匹配。
求出二分图的最大匹配,就要用一个叫匈牙利算法的东西

匈牙利算法

匈牙利算法的核心思想是寻找增广路径,增广路径······算了不上定义了,直接上图:
在这里插入图片描述
这是一条增广路径,这条路径上除了首尾两个点全部都被匹配了,而上面那条增广路径可以变成这样:
在这里插入图片描述

也就是,相对于原来的情况,匹配数+1,匹配的点变成了另一个
匈牙利算法的核心就是不断寻找增广路径,使匹配数越来越多最后达到最大。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int T,ans;
int n,t,tot;
int head[1000010],ver[400010],nxt[400010];
int Match[4005],vis[4010];
void add(int x,int y)
{
   
 ++tot;
 ver[tot]=y;
 nxt[tot]=head[x];
 head[x]=tot;
}
bool dfs(int x)
{
   
 for(int i=head[x];i;i=nxt[i])
 if(!vis[ver[i]])
 {
   
  vis[ver[i]]=1;
  if(!Match[ver[i]]||dfs(Match[ver[i]]))
  {
   
   Match[ver[i]]=x;
   return true;
  }
 }
 return
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值