861. 二分图的最大匹配(匈牙利算法模板)

Posted qdu-lkc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了861. 二分图的最大匹配(匈牙利算法模板)相关的知识,希望对你有一定的参考价值。

给定一个二分图,其中左半部包含n1n1个点(编号1~n1n1),右半部包含n2n2个点(编号1~n2n2),二分图共包含m条边。

数据保证任意一条边的两个端点都不可能在同一部分中。

请你求出二分图的最大匹配数。

二分图的匹配:给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。

二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数即为最大匹配数。

输入格式

第一行包含三个整数 n1n1、 n2n2 和 mm。

接下来m行,每行包含两个整数u和v,表示左半部点集中的点u和右半部点集中的点v之间存在一条边。

输出格式

输出一个整数,表示二分图的最大匹配数。

数据范围

1n1,n25001≤n1,n2≤500,
1un11≤u≤n1,
1vn21≤v≤n2,
1m1051≤m≤105

输入样例:

2 2 4
1 1
1 2
2 1
2 2

输出样例:

2

时间复杂度O(mn) 实际运行时间一般远小于O(mn)

代码:
//匈牙利算法
//思路:一个二分图,从左边子图最多能找到右边子图一一匹配的最大数量
//对于左边子图的某点,找右边子图的某点;如果右边连通的某点没有被匹配,那么可以选择该点作为匹配点;
//否则,右边该点已经被匹配,则看看与右边的这个点匹配的左边的点能否还能找到另一个匹配的右边的点,
//如果能,则把右边这个点让给当前待匹配的左边的点

import java.util.Arrays;
import java.util.Scanner;

public class Main{
        static final int N=505,M=100005;
        static int h[]=new int[N];
        static int e[]=new int[M];
        static int ne[]=new int[M];
        static int n1,n2,m,idx;
        static int match[]=new int[N];
        static boolean vis[]=new boolean[N];
        static void add(int a,int b){
                e[idx]=b;
                ne[idx]=h[a];
                h[a]=idx++;
        }
        static boolean find(int u){
                for(int i=h[u];i!=-1;i=ne[i]){
                        int j=e[i];
                        if(!vis[j]){
                                vis[j]=true;
                                if(match[j]==0 || find(match[j])){//右边的该点没有被匹配或者j对应的左边的点能找到另一个能匹配的右边的点
                                        match[j]=u;
                                        return true;
                                }
                        }
                }
                return false;
        }
        public static void main(String[] args) {
                Scanner scan=new Scanner(System.in);
                Arrays.fill(h, -1);
                n1=scan.nextInt();
                n2=scan.nextInt();
                m=scan.nextInt();
                while(m-->0){
                        int a=scan.nextInt();
                        int b=scan.nextInt();
                        add(a,b);//我们只从左边向右边查找
                }
                int res=0;
                for(int i=1;i<=n1;i++){
                        Arrays.fill(vis, false);//初始化,对于每一个左边的点,一开始它都没有匹配右边的点
                        if(find(i)) res++;
                }
                System.out.println(res);
        }
}

 

以上是关于861. 二分图的最大匹配(匈牙利算法模板)的主要内容,如果未能解决你的问题,请参考以下文章

二分图的判定(染色法)和二分图最大匹配(匈牙利)算法及模板

匈牙利算法,二分图的最大匹配

匈牙利算法 二分图最大匹配题模板

匈牙利算法及其模板 - [二分图最大匹配]

匈牙利算法-二分图的最大匹配

匈牙利 算法&模板