当前位置: 代码迷 >> 综合 >> 【二分图】[LUOGU 3386] 二分图最大匹配
  详细解决方案

【二分图】[LUOGU 3386] 二分图最大匹配

热度:26   发布时间:2024-01-17 00:07:15.0

二分图,,,,一个不得不接触的东西了(主要是想学网络流了,,听大佬说要先从二分图学起,,那就只能先学二分图了,,ヽ(ー_ー)ノ)
(这次就打算改一下学习记录的风格,按类似的专题来写,这样,,博客不会写太长,导致不好找,,,)
(表示在写这篇博客的时候,,,被大宝宝syk叫回去睡觉了,,,只能第二天再补(〃>_<;〃))

(接着补,,,)
,,进入正题:

二分图呢,是要吧一幅图上的点分成两个独立的点集使得这各个个点集中的点相互不连边,而且一副无向图为二分图的充要条件是图中的所有回路的长度均为偶数。(如果是奇数的话就可以理解为展开之后形成是有环的)
然后就介绍下匹配,匹配(或称独立边集)是指这个图之中,任意两条边都没有公共的顶点。这时每个顶点都至多连出一条边,而每一条边都将一对顶点相匹配。
求最大匹配的话就是找到一个最大的边集,使得匹配数最多。
那,怎么解决这样的问题呢???
这就引出了经典的算法——匈牙利算法
先介绍一下增广路:就是这条路径将两个不同集合的两个未匹配顶点通过一系列匹配顶点相连。
匈牙利算法

  1. 匈牙利算法寻找最大匹配,就是通过不断寻找原有匹配的增广路径,因为找到一条匹配的增广路径,就意味着一个更大的匹配 , 其恰好比多一条边。

  2. 对于图来说,最大匹配不是唯一的,但是最大匹配的大小是唯一的。

题目:

几道最大匹配的板子题。
LUOGU 3386
HDU 2063
HDU 1083/POJ 1469

代码:

(这里只贴上LUOGU 3386的AC代码,其他的题几乎都一样,都是板子题)

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){
    if(ch=='-')w=-1;ch=getchar();}while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();return s*w;
}
const int sea=1010;
int n,m,k,ans;
int a[sea][sea],pre[sea],v[sea];
bool hgry(int x)
{
    for(int i=1;i<=m;i++)if(!v[i]&&a[x][i]){
    v[i]=1;if(!pre[i]||hgry(pre[i])){
    pre[i]=x; return 1;}}return 0;
}
int main()
{
    n=read(); m=read(); k=read();memset(pre,0,sizeof(pre));for(int i=1;i<=k;i++) {
    int x=read(),y=read(); a[x][y]=1;}for(int i=1;i<=n;i++){
    memset(v,0,sizeof(v));if(hgry(i)) ans++;}printf("%d\n",ans);return 0;
}

Continue……