外贸营销网站建设介绍,在哪进入网站后台,公众号里的功能怎么开发,南阳做做网站目录 1 基础知识2 模板3 工程化 1 基础知识
二分图中的最大匹配数#xff1a;从二分图中选择一些边#xff08;这些边连接集合A和集合B#xff0c;集合A中结点数目为n1#xff0c;集合B中结点数目为n2#xff09;#xff0c;设为集合S#xff0c;其中任意两条边不共用一… 目录 1 基础知识2 模板3 工程化 1 基础知识
二分图中的最大匹配数从二分图中选择一些边这些边连接集合A和集合B集合A中结点数目为n1集合B中结点数目为n2设为集合S其中任意两条边不共用一个结点。求集合S的最大元素数目即二分图中的最大匹配数。
匈牙利算法的关键步骤
初始化匹配数组match[1~n2] 0。其中match[b] a表示集合B中的结点b匹配了集合A中的结点a。遍历集合A中的每一个结点a初始化状态数组st[1~n2] false其中st[b] false表示集合B中的结点b没有被访问。然后find(x)如果它返回true那么答案加1。
bool find(int a) {//a为集合A中的结点for (auto b : g[x]) {if (!st[b]) {//如果结点b没有被访问st[b] true;if (match[b] 0 || find(match[b])) { //如果结点b没有被匹配或者结点b匹配了的结点可以找到新的match[b] a;return true;}}}return false;
}最终返回答案即为该二分图的最大匹配数。
2 模板
int n1, n2; // n1表示第一个集合中的点数n2表示第二个集合中的点数
int h[N], e[M], ne[M], idx; // 邻接表存储所有边匈牙利算法中只会用到从第一个集合指向第二个集合的边所以这里只用存一个方向的边
int match[N]; // 存储第二个集合中的每个点当前匹配的第一个集合中的点是哪个
bool st[N]; // 表示第二个集合中的每个点是否已经被遍历过bool find(int x)
{for (int i h[x]; i ! -1; i ne[i]){int j e[i];if (!st[j]){st[j] true;if (match[j] 0 || find(match[j])){match[j] x;return true;}}}return false;
}// 求最大匹配数依次枚举第一个集合中的每个点能否匹配第二个集合中的点
int res 0;
for (int i 1; i n1; i )
{memset(st, false, sizeof st);if (find(i)) res ;
}3 工程化
题目1求二分图的最大匹配。
#include iostream
#include cstring
#include vectorusing namespace std;const int N 510;
int n1, n2, m;
vectorvectorint g(N);
int match[N];
bool st[N];bool find(int a) {for (auto b : g[a]) {if (!st[b]) {st[b] true;if (match[b] 0 || find(match[b])) {match[b] a;return true;}}}return false;
}int main() {cin n1 n2 m;int a, b;while (m--) {cin a b;g[a].emplace_back(b);}int res 0;for (int i 1; i n1; i) {memset(st, 0, sizeof st);if (find(i)) res;}cout res endl;return 0;
}