HDOJ2063过山车笔记——匈牙利算法(最大匹配)

题目地址
我在做这道题时距离我写这篇博客已经有一个多月了,当时看到这道题,以为是贪心题,先让最少选择的先上,因为多选择意味着尽量多,现在仔细想了想,是错的,要看怎么错,可以这样想,如果不是最少选择的先上,会不会增加匹配数。
看了discuss,啊!匈牙利算法,厉害。
匈牙利算法博客
趣写算法
写一下基本概念增加印象。
交错路:从未匹配点出发,经过未匹配边,匹配边,未匹配边,匹配边…如此循环
增广路:走交错路,直到遇到第一个未匹配点,如果没有,说明找不到。如果找到了,匹配边增1。
看了基本概念,想要怎么样去实现算法。
首先要解决的第一个问题,如何储存一个图,(因为是第一道遇到的图论题,即便已经学过邻接矩阵,也是没想到用矩阵来存储,所以竟然傻的用一个结构来表示边,每一个结构是一条边,然后有它连接的两点x,y,实在太傻逼了,实在是难处理,又傻又难处理。
回到用邻接矩阵来储存,开了个二维数组,然后顺利存储。
第二个问题,找非匹配点时,如何转移扫描,又想了好久,发现用了一数组来存储匹配点的另一个点,然后通过数组来进行下一步的递归。
第三个问题,如何防止自己找到自己,一个bool数组,就可以。
贴上代码

#include <iostream>
#include <cstring>                                  
using namespace std;
bool map[505][505], used[505];
int girl[505];
int k, m ,n;
bool find(int num) {
	for(int i = 1; i <= m; i++) {
		if(map[num][i] == 1 && used[i] == 0) { //used的作用是寻找匹配点寻找非匹配边时,防止找到匹配边,就是怕自己找到自己
		     used[i] = 1;
			 if(girl[i] == 0 || find(girl[i])) {
			 	girl[i] = num; 
			 	return true;
			 } 
		} 
	}
	return false;
}
int main(void) {
	while(cin >> k && k ) {
		cin >> m >> n;
		memset(used, false, sizeof(used));
		memset(map, false, sizeof(map));
		memset(girl, 0, sizeof(girl));
		int term1, term2;
		for(int i = 0; i < k; i++) {
			cin >> term1 >> term2;
			map[term2][term1] = true;
		}
		int sum = 0;
		for(int i = 1; i <= n; i++) {
			memset(used, false, sizeof(used));
			if(find(i)) {
				sum++;
			}
		}
		cout << sum << endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Greatljc

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值