记录下HDU-2063(二部图-匈牙利算法)

二部图例题HDU-2063(匈牙利算法)
二部图基本概念:
  1. 二部图:一个图中的所有点能够被划分为两个集合,图中的所有边都跨越了集合的边界。(例如:一群人以男女区分为两部分,一些男生喜欢一些女生,一些女生喜欢一些男生,这些男女生和这些喜欢的情况可以称作二部图)
  2. 匹配:匹配是一组边的集合,其中任意两边都没有公共点。(若彼此喜欢男女生能够在一起,某一情况下所有这种能够在一起的关系称为匹配,这一情况下在一起的关系就称为匹配边,原本喜欢但是没有在一起的就称为未匹配边)
  3. 最大匹配:所有匹配中,边数最多的一个匹配关系。(能够使得最多对男女生在一起的一种情况)
  4. 完美匹配:一个图中所有顶点都是匹配点(所有男生刚好和所有女生彼此之间一一匹配的一种情况)
匈牙利算法:

交错路:从一个未匹配点出发,依次遍历未匹配边、匹配边、未匹配边、匹配边. . .交错着最后回到未匹配点的路径。
增广路径:起点和终点都是未匹配点的交错路径。增广路径的存在说明匹配数还能够增加。所以它才叫增广路径的吧

算法核心:对于一种匹配的情况,若能够找到它的一条增广路径(或者能够对这种匹配进行补充,这种情况直接更新就好了),说明这一情况下还有另外的一种情况使得匹配数更大。而这种更大匹配数的情况就是原本的匹配点与未匹配点交换的情况。即舍弃原本匹配的,改变为新的匹配(原本的未匹配)。

于是我们选择二部图中的一个部进行遍历,这个部中的点作为起始选择的未匹配点。判断目前的匹配情况下能否找到以这个点为起点的增广路径(或者这个点能够作为新的补充),如果可以就进行更新。直到这个部的所有起点都遍历完了。

为了祭奠这道题二部图匹配-HDU-2063-过山车

最后放上代码然后下班:

#include<iostream>
#include<stdio.h>
#include<vector>
#define Mx 10086
using namespace std;

//万事开头难

int match[Mx];	//match[i]表示第i个女生当前匹配的男生编号,0表示没有
vector<int>boys[Mx];//记录每个男生可能匹配到的女生
int vis[Mx];	//记录在这一次选择中被访问过的结点
int bn, gn, n;

/*dfs==true的条件是这个兄弟找到了匹配,
而且不会使得其他已经找到匹配的兄弟失去匹配,包含了对match的更新*/
bool dfs(int x) {
	//细节转int
	for (int i = 0; i < (int)boys[x].size(); i++) {
		int g = boys[x][i];
		if (vis[g] == 0) {
			vis[g] = 1;
			if (match[g] == 0 || dfs(match[g])) {
				match[g] = x;
				return true;
			}
		}
	}
	return false;
}


int main() {
	while (scanf("%d", &n) && n && scanf("%d %d", &bn, &gn)) {
		memset(match, 0, sizeof(match));
		for (int i = 0; i < gn+1; i++) {
			boys[i].clear();
		}
		for (int i = 0; i < n; i++) {
			int a, b;	//a为男生编号,b为女生编号
			scanf("%d %d", &a, &b);
			boys[a].push_back(b);
		}
		int ans = 0;
		//选择男生部,作为起始的未匹配点进行遍历
		for (int i = 1; i <= bn; i++) {
			memset(vis, 0, sizeof(vis));
			if (dfs(i)) {
				ans++;
			}
		}
		printf("%d\n", ans);

	}
	return 0;
}
参考来自其它大佬的文章:

SixDayCoder:二分图的最大匹配——匈牙利算法
二分图-2SAT
一只大秀逗:匈牙利算法(简单易懂)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值