帮我写一个匈牙利算法,使用C语言
时间: 2023-05-29 11:05:25 浏览: 55
以下是一个简单的匈牙利算法的C语言实现:
```c
#include <stdio.h>
#include <stdbool.h>
#define MAX_N 100
#define MAX_M 100
int n, m; // n是左部集合中元素的数量,m是右部集合中元素的数量
bool g[MAX_N][MAX_M]; // 二分图的邻接矩阵表示
int match[MAX_M]; // 记录右部集合中每个元素的匹配情况,-1表示未匹配
bool dfs(int u, bool vis[], int link[]) {
for (int v = 0; v < m; v++) {
if (g[u][v] && !vis[v]) {
vis[v] = true;
if (link[v] == -1 || dfs(link[v], vis, link)) {
link[v] = u;
return true;
}
}
}
return false;
}
int hungarian() {
int cnt = 0;
int link[MAX_M];
for (int i = 0; i < m; i++) {
link[i] = -1;
}
for (int u = 0; u < n; u++) {
bool vis[MAX_M] = {false};
if (dfs(u, vis, link)) {
cnt++;
}
}
return cnt;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int x;
scanf("%d", &x);
g[i][j] = (x == 1);
}
}
int ans = hungarian();
printf("%d\n", ans);
return 0;
}
```
匈牙利算法的核心是递归搜索,每次从左部集合中的一个未匹配节点开始,尝试匹配它能够到达的所有右部集合中的节点。如果当前右部节点未匹配,或者它已经与其他左部节点匹配但可以尝试重新匹配,就将该右部节点与当前左部节点匹配,并返回成功。否则继续查找未匹配的右部节点。如果所有右部节点都已经被尝试过,但没有成功匹配,说明当前左部节点无法匹配任何右部节点,返回失败。
在实现过程中,我们用一个bool类型的数组vis记录右部节点是否已经被访问过,避免重复搜索。用一个int类型的数组link记录右部节点的匹配情况,-1表示未匹配。
最后,我们遍历所有左部集合中的未匹配节点,尝试将它们匹配到右部集合中的节点上。如果成功匹配,则计数器cnt加1。最终返回cnt即为最大匹配数。