Loading docs/graph/bi-graph.md +10 −22 Original line number Diff line number Diff line Loading @@ -31,11 +31,6 @@ ### 二分图匹配 #### 霍尔定理 设二部图 $G=<V_1, V_2, E>, |V_1| \leq |V_2|$ ,则 $G$ 中存在 $V_1$ 到 $V_2$ 的完备匹配当且仅当对于任意的 $S \subset V_1$ ,均有 $|S|\leq|N(S)|$ ,其中 $N(S)=\Cup_{v_i \in S}{N(V_i)}$ ,是 $S$ 的邻域。 #### 匹配 给定一个二分图$G$,若在$G$的子图$M$中,任意两条边都没有公共节点,那么称$M$为二分图$G$的一个匹配,且M的边数为匹配数。 Loading @@ -44,11 +39,11 @@ 寻找二分图边数最大的匹配称为最大匹配问题。 对此,有解决此问题的匈牙利算法。 对此,有解决此问题的**匈牙利算法**,时间复杂度为$O(NM)$。 算法步骤大致如下: 1.首先从任意一个未配对的点$u$开始,选择他的任意一条条边($u$-$v$),如此时$v$还未配对,则配对成功,配对数加一,若$v$已经配对,则尝试寻找v的配对的另一个配对(该步骤可能会被递归的被执行多次),若该尝试成功,则配对成功,配对数加一。 1.首先从任意一个未配对的点$u$开始,选择他的任意一条边($u$-$v$),如此时$v$还未配对,则配对成功,配对数加一,若$v$已经配对,则尝试寻找$v$的配对的另一个配对(该步骤可能会被递归的被执行多次),若该尝试成功,则配对成功,配对数加一。 2.若果上一步配对不成功,那么选择重新选择一条未被选择过的边,重复上一步。 Loading @@ -62,10 +57,10 @@  接下来对节点3尝试匹配,选择边(3-4),发现4已经有匹配了,我们尝试寻找4的匹配的其他匹配,既1的其他匹配。 这个匹配显然只能从未被选择的边里找(灰色的),我们可以遍历1的所有边,寻找未被选择的,我们很容易找到边(1-5)。 接下来对节点3尝试匹配,选择边(3-4),但发现4已经有匹配了,我们尝试寻找4的匹配的其他匹配,即1的其他匹配。 这个匹配显然只能从未被选择的边里找(灰色的),我们可以遍历1的所有边,寻找未被选择的,很容易找到边(1-5)。 我们发现5已经被匹配了,所以我们尝试寻找5的匹配的其他匹配,即2的其他匹配。类是的,我们可以找到6。 我们发现5已经被匹配了,所以我们尝试寻找5的匹配的其他匹配,即2的其他匹配。类似的,可以找到6。  Loading @@ -73,23 +68,19 @@  我们可以发现,当我们尝试对节点3进行匹配时,我们走过了一条路径(3-4-1-5-2-6),最后找到了新的匹配方案,我们把这样的道路叫做**增广路**,其本质是一条起点和终点都是未匹配节点的路径。 可以发现,当尝试对节点3进行匹配时,走过了一条路径(3-4-1-5-2-6),最后找到了新的匹配方案,我们把这样的道路叫做**增广路**,其本质是一条起点和终点都是未匹配节点的路径。 匈牙利算法执行的过程也可以看作是不断寻找增广路的过程,当在当前匹配方案下再也找不到增广路,那么当前匹配方案便是最大匹配了。 代码如下: ```cpp #include<bits/stdc++.h> using namespace std; const int N = 2e3 + 10; int n, m, e; vector<int> G[N]; //使用邻接表来储存边 int match[N], vis[N]; bool dfs(int u){ int len = G[u].size(); for(int i = 0; i < len; i++){ //遍历每一条边 Loading @@ -104,9 +95,7 @@ bool dfs(int u){ } return 0; } int main(){ scanf("%d %d %d", &n, &m, &e); for(int i = 1; i <= e; i++){ int a, b; Loading @@ -115,25 +104,24 @@ int main(){ G[a].push_back(n + b); G[n + b].push_back(a); } int ans = 0; for(int i = 1; i <= n; i++){ //对每一个点尝试匹配 for(int j = 1; j <= n + m; j++) vis[j] = 0; if(dfs(i)) ans++; } printf("%d", ans); return 0; } ``` 例题参考: [洛谷 P3386 【模板】二分图匹配](https://www.luogu.com.cn/problem/P3386) #### 最大权匹配 #### 霍尔定理 设二部图 $G=<V_1, V_2, E>, |V_1| \leq |V_2|$ ,则 $G$ 中存在 $V_1$ 到 $V_2$ 的完备匹配当且仅当对于任意的 $S \subset V_1$ ,均有 $|S|\leq|N(S)|$ ,其中 $N(S)=\Cup_{v_i \in S}{N(V_i)}$ ,是 $S$ 的邻域。 ## 一般图匹配 Loading
docs/graph/bi-graph.md +10 −22 Original line number Diff line number Diff line Loading @@ -31,11 +31,6 @@ ### 二分图匹配 #### 霍尔定理 设二部图 $G=<V_1, V_2, E>, |V_1| \leq |V_2|$ ,则 $G$ 中存在 $V_1$ 到 $V_2$ 的完备匹配当且仅当对于任意的 $S \subset V_1$ ,均有 $|S|\leq|N(S)|$ ,其中 $N(S)=\Cup_{v_i \in S}{N(V_i)}$ ,是 $S$ 的邻域。 #### 匹配 给定一个二分图$G$,若在$G$的子图$M$中,任意两条边都没有公共节点,那么称$M$为二分图$G$的一个匹配,且M的边数为匹配数。 Loading @@ -44,11 +39,11 @@ 寻找二分图边数最大的匹配称为最大匹配问题。 对此,有解决此问题的匈牙利算法。 对此,有解决此问题的**匈牙利算法**,时间复杂度为$O(NM)$。 算法步骤大致如下: 1.首先从任意一个未配对的点$u$开始,选择他的任意一条条边($u$-$v$),如此时$v$还未配对,则配对成功,配对数加一,若$v$已经配对,则尝试寻找v的配对的另一个配对(该步骤可能会被递归的被执行多次),若该尝试成功,则配对成功,配对数加一。 1.首先从任意一个未配对的点$u$开始,选择他的任意一条边($u$-$v$),如此时$v$还未配对,则配对成功,配对数加一,若$v$已经配对,则尝试寻找$v$的配对的另一个配对(该步骤可能会被递归的被执行多次),若该尝试成功,则配对成功,配对数加一。 2.若果上一步配对不成功,那么选择重新选择一条未被选择过的边,重复上一步。 Loading @@ -62,10 +57,10 @@  接下来对节点3尝试匹配,选择边(3-4),发现4已经有匹配了,我们尝试寻找4的匹配的其他匹配,既1的其他匹配。 这个匹配显然只能从未被选择的边里找(灰色的),我们可以遍历1的所有边,寻找未被选择的,我们很容易找到边(1-5)。 接下来对节点3尝试匹配,选择边(3-4),但发现4已经有匹配了,我们尝试寻找4的匹配的其他匹配,即1的其他匹配。 这个匹配显然只能从未被选择的边里找(灰色的),我们可以遍历1的所有边,寻找未被选择的,很容易找到边(1-5)。 我们发现5已经被匹配了,所以我们尝试寻找5的匹配的其他匹配,即2的其他匹配。类是的,我们可以找到6。 我们发现5已经被匹配了,所以我们尝试寻找5的匹配的其他匹配,即2的其他匹配。类似的,可以找到6。  Loading @@ -73,23 +68,19 @@  我们可以发现,当我们尝试对节点3进行匹配时,我们走过了一条路径(3-4-1-5-2-6),最后找到了新的匹配方案,我们把这样的道路叫做**增广路**,其本质是一条起点和终点都是未匹配节点的路径。 可以发现,当尝试对节点3进行匹配时,走过了一条路径(3-4-1-5-2-6),最后找到了新的匹配方案,我们把这样的道路叫做**增广路**,其本质是一条起点和终点都是未匹配节点的路径。 匈牙利算法执行的过程也可以看作是不断寻找增广路的过程,当在当前匹配方案下再也找不到增广路,那么当前匹配方案便是最大匹配了。 代码如下: ```cpp #include<bits/stdc++.h> using namespace std; const int N = 2e3 + 10; int n, m, e; vector<int> G[N]; //使用邻接表来储存边 int match[N], vis[N]; bool dfs(int u){ int len = G[u].size(); for(int i = 0; i < len; i++){ //遍历每一条边 Loading @@ -104,9 +95,7 @@ bool dfs(int u){ } return 0; } int main(){ scanf("%d %d %d", &n, &m, &e); for(int i = 1; i <= e; i++){ int a, b; Loading @@ -115,25 +104,24 @@ int main(){ G[a].push_back(n + b); G[n + b].push_back(a); } int ans = 0; for(int i = 1; i <= n; i++){ //对每一个点尝试匹配 for(int j = 1; j <= n + m; j++) vis[j] = 0; if(dfs(i)) ans++; } printf("%d", ans); return 0; } ``` 例题参考: [洛谷 P3386 【模板】二分图匹配](https://www.luogu.com.cn/problem/P3386) #### 最大权匹配 #### 霍尔定理 设二部图 $G=<V_1, V_2, E>, |V_1| \leq |V_2|$ ,则 $G$ 中存在 $V_1$ 到 $V_2$ 的完备匹配当且仅当对于任意的 $S \subset V_1$ ,均有 $|S|\leq|N(S)|$ ,其中 $N(S)=\Cup_{v_i \in S}{N(V_i)}$ ,是 $S$ 的邻域。 ## 一般图匹配