先上一些概念:
- “任意两条边都没有公共端点”的最大的边的集合称为二分图的最大匹配。
- 二分图的一组匹配S是最大匹配,当且仅当图中不存在S的增广路。
- 二分图匹配的要素有2,一是0要素,节点可以分成独立的两个集合,每个集合内部有0条边;1要素,每个节点只能与1条边匹配。
- 二分图最小点覆盖(选最少的点使得所有边都被覆盖)包含的点数==最大匹配包含的边数
- 二分图最大独立集(任意两点之间都没有边相连,包含的点数最多)==n-最大匹配数。
二分图最大匹配的板子,复杂度是(V*E)点数乘以边数:
const int maxn=409;
const int maxm=1e5+7;
struct Edge{
int v,next;
}edge[maxm];
int head[maxn],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void add(int u,int v){
edge[top].v=v;
edge[top].next=head[u];
head[u]=top++;
}
int match[maxn];
bool vis[maxn];
bool dfs(int u){
int v;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].v;
if(!vis[v]){
vis[v]=1;
if(!match[v]||dfs(match[v])){
match[v]=u;
return 1;
}
}
}
return 0;
}
int main(){
int res=0;//答案;
for(int i=1;i<=n;++i){//一边的点;
memset(vis,0,sizeof(vis));
if(dfs(i)) ++res;
}
return 0;
}
二分图匹配的模型有两个要素:
1、节点能分成独立的两个集合,每个集合内部有0条边。
2、每个节点只能与1条匹配边匹配。
显然这个答案具有单调性,所以我们可以二分答案,然后比答案大的两个人显然不可以分到一起,所以我们建图,将两个人连边,然后跑一下无向图染色就行了,不用匈牙利。
#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+7;
const int maxn=2e4+7;
struct Node{
int u,v,w;
}node[maxm];
struct Edge{
int v,next;
}edge[maxm<<1];
int head[maxn],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void add(int u,int v){
edge[top].v=v;
edge[top].next=head[u];
head[u]=top++;
}
int n,m;
bool color[maxn],vis[maxn];
bool dfs(int u,bool f){
color[u]=f;
vis[u]=1;
int v;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].v;
if(!vis[v]){
bool flag=dfs(v,!f);
if(!flag) return 0;
}
else if(color[v]==color[u]) return 0;
}
return 1;
}
bool check(