本专栏持续输出数据结构题目集,欢迎订阅。
题目
请编写程序,实现求解无权二部图最大匹配的匈牙利算法。
输入格式:
输入首先在第一行给出 3 个正整数,依次为二部图 G=(U∪V,E) 中 U 点集顶点数、V 点集顶点数(均不超过 100)和边数 m。
随后 m 行,每行给出一条连接 U 点集顶点和 V 点集顶点的边,格式为 u v,其中 u 属于 U,v 属于 V。两个点集的顶点编号均从 0 开始。同行数字间以一个空格分隔。
输出格式:
在一行中输出 最大匹配值 = x,其中 x 为最大匹配数。
输入样例:
4 3 7
0 0
0 1
1 1
1 2
2 0
2 1
3 2
输出样例:
最大匹配值 = 3
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_U 100
#define MAX_V 100
int graph[MAX_U][MAX_V]; // 二部图的邻接矩阵表示
int matchV[MAX_V]; // 记录V中顶点的匹配情况
int visited[MAX_V]; // 记录V中顶点是否在本次DFS中被访问过
int u_size, v_size, m; // U和V的顶点数,边数
// 为U中顶点u寻找增广路径
int dfs(int u) {
for (int v = 0; v < v_size; v++) {
if (graph[u][v] && !visited[v]) {
visited[v] = 1;
// 如果v未匹配,或者v的匹配对象可以找到新的匹配
if (matchV[v] == -1 || dfs(matchV[v])) {
matchV[v] = u;
return 1;
}
}
}
return 0;
}
int hungarian() {
int result = 0;
memset(matchV, -1, sizeof(matchV)); // 初始化V中顶点均未匹配
for (int u = 0; u < u_size; u++) {
memset(visited, 0, sizeof(visited)); // 每次DFS前重置访问标记
if (dfs(u)) {
result++; // 找到一条增广路径,匹配数加1
}
}
return result;
}
int main() {
// 读取输入
scanf("%d %d %d", &u_size, &v_size, &m);
// 初始化图
memset(graph, 0, sizeof(graph));
// 读取边信息
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d %d", &u, &v);
graph[u][v] = 1; // 存在边(u,v)
}
// 计算最大匹配
int max_matching = hungarian();
// 输出结果
printf("最大匹配值 = %d\n", max_matching);
return 0;
}