Commit 115f668a authored by ZerQAQ's avatar ZerQAQ
Browse files

bi-graph

parent 48add129
Loading
Loading
Loading
Loading
+10 −22
Original line number Diff line number Diff line
@@ -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的边数为匹配数。
@@ -44,11 +39,11 @@

寻找二分图边数最大的匹配称为最大匹配问题。

对此,有解决此问题的匈牙利算法。
对此,有解决此问题的**匈牙利算法**,时间复杂度为$O(NM)$

算法步骤大致如下:

1.首先从任意一个未配对的点$u$开始,选择他的任意一条边($u$-$v$),如此时$v$还未配对,则配对成功,配对数加一,若$v$已经配对,则尝试寻找v的配对的另一个配对(该步骤可能会被递归的被执行多次),若该尝试成功,则配对成功,配对数加一。
1.首先从任意一个未配对的点$u$开始,选择他的任意一条边($u$-$v$),如此时$v$还未配对,则配对成功,配对数加一,若$v$已经配对,则尝试寻找$v$的配对的另一个配对(该步骤可能会被递归的被执行多次),若该尝试成功,则配对成功,配对数加一。

2.若果上一步配对不成功,那么选择重新选择一条未被选择过的边,重复上一步。

@@ -62,10 +57,10 @@

![](./images/bi-graph-2.png)

接下来对节点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。

![](./images/bi-graph-3.png)

@@ -73,23 +68,19 @@

![](./images/bi-graph-4.png)

我们可以发现,当我们尝试对节点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++){ //遍历每一条边
@@ -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;
@@ -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$ 的邻域。

## 一般图匹配