实验题目:无向图的最大匹配
实验目的:
1、掌握最大匹配,交错路径的定义;
2、掌握最大匹配的求解方法。
实验要求:
知识回顾
1、最大匹配
无向图G=<V,E>, E⊆E
匹配(边独立集): ∀e, f∈E, e,f 不相邻
极大匹配: E是匹配, 其真母集都不是
最大匹配: |E|最大的匹配
匹配数: 1(G)=|E*|, E*是最大匹配
2、设M是G中匹配
交错路径(圈): 在M和E-M中交替取边的路径(圈)
模拟代码
/*
输入:无向简单连通图的关联矩阵
输出:此图的任意一个最大匹配及匹配数
解题思路:
匹配的定义:图的边集的一个子集,其中任何两条边都不相邻
最大匹配:再加一条边就不是匹配
匹配数:最大匹配的边数
我的思路是往集合里面加边,每次加的边不能和边集里的边相邻
如何判断相邻:
遍历边集,新加的边不能和原有的边有相同的端点
*/
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n = 0; // 顶点数
int m = 0; // 边数
printf("请输入图的顶点数:\n");
scanf("%d", &n);
printf("请输入图的边数:\n");
scanf("%d", &m);
vector<vector<int> > M(n, vector<int>(m, 0));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
scanf("%d", &M[i][j]);
}
}
unordered_set<int> E; // 存放匹配边集
E.insert(0); // 先加入e1
unordered_set<int> V; // 存放匹配点集
for (int i = 0; i < n; ++i) {
if (M[i][0] == 1) {
V.insert(i);
}
}
for (int j = 1; j < m; ++j) {
int flag = 0; // 为2的时候说明该边不和匹配中的边关联
int t1 = -1;
int t2 = -1;
for (int i = 0; i < n; ++i) {
if (M[i][j] == 1) {
if (V.count(i) == 0) { // 其中一个端点不和匹配中的边关联,标志位加一
flag++;
if (t1 == -1) {
t1 = i;
}
else if (t2 == -1) {
t2 = i;
}
else {
printf("一条边不可能有超过两个顶点,输入可能出错了\n");
return 0;
}
}
}
}
// 该边可以加入匹配中
if (flag == 2) {
E.insert(j);
V.insert(t1);
V.insert(t2);
}
}
printf("该图的一个最大匹配集为:\n");
auto it = E.begin();
printf("{e%d", *it + 1);
++it;
for (; it != E.end(); ++it) {
printf(", e%d", *it + 1);
}
printf("}\n");
printf("最大匹配数为%d\n", E.size());
return 0;
}
/*
测试数据:
4 5
1 0 0 1 1
1 1 0 0 0
0 0 1 1 0
0 1 1 0 1
5 6
1 0 0 1 0 1
1 1 0 0 0 0
0 1 1 0 0 0
0 0 1 1 1 0
0 0 0 0 1 1
*/