匈牙利算法

匈牙利算法

算法用途:用于求最大匹配数,比如n个男生和m个女生,每个人都有暗恋的对象(一个人可能暗恋多个人)求能凑够的情侣的数量。

算法思想主要利用深度优先搜索(DFS)来实现。比如男生A喜欢女生B,但是女生B已经有了男朋友C。那就在男生C的暗恋对象中找到一个女生D,让C与D成为情侣,那么这样女生B就没有男朋友了,于是A和B就可以成为情侣。在这里插入图片描述
在本图中,A<->B、A<->C、B<->E、C<->G,他们相互喜欢。我们先匹配A,发现A可以与B组成情侣;我们继续看E,发现E喜欢的B已经有情侣了,那么就让B的情侣A去另找情侣,发现A又可以找到C,于是让A与C成为情侣,进而E就可以和B在一起了;继续看G,我们发现G喜欢的C已经有情侣A了,于是我们企图让A再去找其他的情侣,于是又找到了B,企图和B在一起,但是发现B也有情侣E,那么再尝试找E能否和未匹配的人在一起,发现不可以,而且路已经走到了尽头,所以一路返回,告知G没有人可以与他在一起,匹配失败。故本图的最大匹配对数就是2对。

算法步骤:
①:建立关系,也就是所谓的相互暗恋关系
②:遍历每个人(也可以只遍历男生或只遍历女生),尝试能否找到伴侣,找到就让答案+1
③:也就是寻找函数,此函数运用深度优先遍历进行回溯遍历,并且在过程中记录遍历到人的当前的情侣是谁

核心算法:

int dfs(int x) {//注意深搜每个人时,都是要memset数组v
	int i;
	for(i=0;i<vt[x].size();i++) {
		int y = vt[x][i];
		if(!v[y]) {
			v[y] = 1;
			if(father[y]==-1||dfs(father[y])) {//如果喜欢的人没有还单身(也就是father[y]等于-1)
			//那就直接建立联系,否则dfs喜欢的人的情侣,继续深搜。
				father[y] = x;//建立联系
				return 1;
			}
		}
	}
	return 0;
}

经典例题Swap Free
题目大意:给n个字符串,长度相同,都由相同个数的每个字母组成。求选择最大的m个字符串组成一个集合,使他们不能两两互相转化(转化是指将字符串A中的两个字符交换位置可以的到B)

思路:重点在于如何将问题落实在算法上。既然要求不能两两互相转化。那么我们就先求能两两互相转化的字符串的个数为cnt,那么cnt/2个字符串一定是不能两两转化的。那么本身还有n-cnt个孤立点(不可能与其他任何n-1个点相互转化)那么答案就是n-cnt+cnt/2了。那么只用在可以转化的两个字符串之间建立联系(也就是相互暗恋的关系),然后跑一个匈牙利算法求出最大匹配数即可。

题目代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 550;

int v[N],father[N];
vector<int> vt[N];
vector<string> vet;

int is(int x,int y) {
	int i;
	string s = vet[x],s1 = vet[y];
	int l = s.size();
	int sum = 0;
	for(i=0;i<l;i++) {
		if(s[i]!=s1[i])sum++;
	}
	if(sum==2)return 1;
	return 0;
}
int dfs(int x) {
	int i;
	for(i=0;i<vt[x].size();i++) {
		int y = vt[x][i];
		if(!v[y]) {
			v[y] = 1;
			if(father[y]==-1||dfs(father[y])) {
				father[y] = x;
				return 1;
			}
		}
	}
	return 0;
}
int main() {
	string x;
	int n,m,i,j,k;
	cin >> n;
	for(i=0;i<n;i++) {
		cin >> x;
		vet.push_back(x);
	}	
	for(i=0;i<n;i++) {
		for(j=i+1;j<n;j++) {
			if(is(i,j)) {
				vt[i].push_back(j);
				vt[j].push_back(i);
			}
		}
	}
	int ans = 0;
	memset(father,-1,sizeof father);
	for(i=0;i<n;i++) {
		memset(v,0,sizeof v);
		if(dfs(i))ans++;
	}
	printf("%d\n",n-(ans)/2);
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
匈牙利算法,也称为二分图最大匹配算法,是一种解决二分图最大匹配问题的经典算法。它的目标是在一个二分图中找到最大的匹配数,即找到最大的能够互相配对的节点对数。 Python是一种高级编程语言,具有简洁、易读、易学的特点,广泛应用于各个领域。在Python中,我们可以使用网络流算法库或者自己实现匈牙利算法来解决二分图最大匹配问题。 以下是匈牙利算法的基本思想和步骤: 1. 初始化一个空的匹配集合。 2. 对于每个未匹配的左侧节点,尝试将其与一个未匹配的右侧节点进行匹配。 3. 如果右侧节点未被匹配,或者已被匹配但可以通过其他路径重新匹配,那么将左侧节点与右侧节点进行匹配,并将右侧节点标记为已匹配。 4. 如果右侧节点已被匹配且无法重新匹配,那么尝试将右侧节点的当前匹配节点重新匹配到其他未匹配的左侧节点。 5. 重复步骤3和步骤4,直到无法找到更多的匹配。 在Python中,可以使用networkx库来实现匈牙利算法。以下是一个使用networkx库解决二分图最大匹配问题的示例代码: ```python import networkx as nx # 创建一个空的二分图 G = nx.Graph() # 添加左侧节点 G.add_nodes_from(['A', 'B', 'C']) # 添加右侧节点 G.add_nodes_from([1, 2, 3]) # 添加边 G.add_edges_from([('A', 1), ('A', 2), ('B', 2), ('C', 3)]) # 使用匈牙利算法求解最大匹配 matching = nx.bipartite.maximum_matching(G) # 输出最大匹配结果 print(matching) ``` 以上代码中,我们首先创建了一个空的二分图,并添加了左侧节点和右侧节点。然后,我们使用`nx.bipartite.maximum_matching`函数来求解最大匹配,并将结果存储在`matching`变量中。最后,我们输出最大匹配结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值