算法笔记_137:二分图的最大匹配(Java)
目录
1 问题描述
何为二分图的最大匹配问题?
引用自百度百科:
首先得说明一下何为匹配:
给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。
极大匹配(Maximal Matching)是指在当前已完成的匹配下,无法再通过增加未完成匹配的边的方式来增加匹配的边数。最大匹配(maximum matching)是所有极大匹配当中边数最大的一个匹配。选择这样的边数最大的子集称为图的最大匹配问题。
特别注意:二分图的最大匹配,其图为无权连通图。二分图的最大权分配,其图才是有权连通图,这两者是不同的概念。
2 解决方案
此处采用DFS方法。
具体代码如下:
package com.liuzhen.practice; import java.util.Scanner; public class Main { public static int n = 0, m = 0; //二分图的左边和右边顶点数目
/*
* 参数map:给定的二分图,map[i][j]等于1表示i到j连通,为0则表示不连通
* 参数linked:linked[i] = u表示顶点i与顶点u连接
* 参数start:当前start顶点出发,寻找增广路径
* 函数功能:如果能够找到已顶点start开始的增广路径返回true,否则返回false
*/
public boolean dfs(int[][] map, boolean[] used, int[] linked, int start) {
for(int i = 0;i < m;i++) {
if(used[i] == false && map[start][i] == 1) {
used[i] = true;
if(linked[i] == -1 || dfs(map, used, linked, linked[i])) {
linked[i] = start;
return true;
}
}
}
return false;
} public int getMaxNum(int[][] map) {
int count = 0;
int[] linked = new int[m];
for(int i = 0;i < m;i++)
linked[i] = -1;
for(int i = 0;i < n;i++) {
boolean[] used = new boolean[m]; //初始化m部分顶点均为被访问
if(dfs(map, used, linked, i)) //从顶点i出发能够得到一条增广路径
count++;
}
return count;
} public static void main(String[] args) {
Main test = new Main();
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
int[][] map = new int[n][m];
int k = in.nextInt(); //二分图中边的数目
for(int i = 0;i < k;i++) {
int a = in.nextInt(); //n部分中的顶点
int b = in.nextInt(); //m部分中顶点
map[a][b] = 1;
}
System.out.println(test.getMaxNum(map));
}
}
参考资料:
算法笔记_137:二分图的最大匹配(Java)的更多相关文章
- 算法笔记_023:拓扑排序(Java)
目录 1 问题描述 2 解决方案 2.1 基于减治法实现 2.2 基于深度优先查找实现 1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进 ...
- 算法笔记_139:二分图的最大权匹配(Java)
目录 1 问题描述 2 解决方案 1 问题描述 何为二分图的最大权匹配问题? 最大权二分匹配问题就是给二分图的每条边一个权值,选择若干不相交的边,得到的总权值最大. 2 解决方案 对于此问题的讲解 ...
- 【算法笔记】二分图与KM算法(当你试图只看蓝书学算法
前言 呜,好久没写博客了,DDL 也有好多,一不留神就轮到我了呜. 看了一眼其它同学写的博客,什么数模啊,什么 CTF 啊,什么 Python 爬虫啊,感觉自己真是越来越菜了呜. 然后在我一愁莫展之际 ...
- 算法笔记_228:信用卡号校验(Java)
目录 1 问题描述 2 解决方案 1 问题描述 当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过Luhn算法来验证 ...
- 算法笔记_138:稳定婚姻问题(Java)
目录 1 问题描述 2 解决方案 1 问题描述 何为稳定婚姻问题? 有一个男士的集合Y = {m1,m2,m3...,mn}和一个女士的计划X = {n1,n2,n3,...,nn}.每一个男士有 ...
- 算法笔记_132:最大流量问题(Java)
目录 1 问题描述 2 解决方案 1 问题描述 何为最大流量问题? 给定一个有向图,并为每一个顶点设定编号为0~n,现在求取从顶点0(PS:也可以称为源点)到顶点n(PS:也可以称为汇点)后,顶点 ...
- 算法笔记_040:二进制幂(Java)
目录 1 问题描述 2 解决方案 2.1 从左至右二进制幂 2.2 从右至左二进制幂 1 问题描述 使用n的二进制表示,计算a的n次方. 2 解决方案 2.1 从左至右二进制幂 此方法计算a的n次 ...
- 算法笔记_014:合并排序(Java)
1 问题描述 给定一组数据,使用合并排序得到这组数据的非降序排列. 2 解决方案 2.1 合并排序原理简介 引用自百度百科: 合并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Div ...
- 算法笔记_233:二阶魔方旋转(Java)
目录 1 问题描述 2 解决方案 1 问题描述 魔方可以对它的6个面自由旋转. 我们来操作一个2阶魔方(如图1所示): 为了描述方便,我们为它建立了坐标系. 各个面的初始状态如下:x轴正向:绿x轴 ...
随机推荐
- PHP 笔记——Array 数组
要点 说明 数组构成 数组是由一个或多个数组元素组成的 数组元素 每个数组元素由键(Key)和值(Value)构成 键 元素的识别名称,也被称为数组下标 值 元素的内容 映射 键 和 值 之间存在一种 ...
- bzoj 3289 莫队 逆序对
莫队维护逆序对,区间左右增减要分类讨论. 记得离散化. /************************************************************** Problem: ...
- Codeforces Round #245 (Div. 2) B. Balls Game 并查集
B. Balls Game Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/430/problem ...
- 使用pyplot和seaborn进行画图
pyplot的一些知识 matplotlab中的对象: matplotlib是面向对象的,在画图的时候我们了解一些对象,对我们画图是有帮助的.绘图的对象大致分为三层: backend_bases.Fi ...
- 网络抓包工具wireshark常用封装过滤规则
过滤器的区别 捕捉过滤器(CaptureFilters):用于决定将什么样的信息记录在捕捉结果中.需要在开始捕捉前设置.显示过滤器(DisplayFilters):在捕捉结果中进行详细查找.他们可以在 ...
- Android开发:ListView加上长按事件
为ListView加上长按事件 lvMain.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public b ...
- Tomcat配置域名和虚拟文件夹
说明: 我在本机中添加域名模拟,假设是主机直接配置也能够使用.我用的tomcat是apache-tomcat-7.0.42 本地添加域名 本文介绍怎样通过改动tomcat的配置.实现通过IP地址或者域 ...
- sql 内连接、外连接、自然连接等各种连接
1.内联接(典型的联接运算,使用像 = 或 <> 之类的比较运算符).包括相等联接和自然联接. 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 students和c ...
- MFC 获取DC和输出文字、获取指定区域
缓存DC的作用:解决闪烁问题 CRect rect; GetClientRect(rect);获取view视图的区域 CClientDC dc(this); 创建了DC可作图 pdc->Dra ...
- Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字
Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...