---
# System prepended metadata

title: Solving Maximum Matching Problem 結報
tags: [Algorithm_Lab]

---

<style>
    html, body, .ui-content {
    background: #222222;
    color: #00BFFF;
}
::-webkit-scrollbar {
    width: 10px;
}
::-webkit-scrollbar-track {
    background: transparent;
}
::-webkit-scrollbar-thumb {
    background: linear-gradient(180deg, #2BE8CF60 0%, #2B83E860 100%);
    border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
    background: linear-gradient(180deg, #2BE8CF95 0%, #2B83E895 100%);
}
    /* 設定 code 模板 */
    .markdown-body code,
.markdown-body tt {
    background-color: #ffffff36;
}
.markdown-body .highlight pre,
.markdown-body pre {
    color: #ddd;
    background-color: #00000036;
}
.hljs-tag {
    color: #ddd;
}
.token.operator {
  background-color: transparent;
}
   
</style>
###### tags: `Algorithm_Lab`

# Solving Maximum Matching Problem 結報
## OJ AC截圖
![](https://hackmd.io/_uploads/rJCwiEPS3.png)

## Code
```cpp=
#include <bits/stdc++.h>
#define INF 100000
using namespace std;

bool bellman_ford(int n, int &s, int &t, vector<vector<pair<int, double>>> &edges) {
    vector<double> dis(n, INF);
    vector<int> pi(n, -1);
    dis[s] = 0;
    for (int i = 0; i < n - 1; ++i) {
        bool check = false;
        for (int j = 0; j < n; ++j) {
            for (auto &it : edges[j]) {
                double temp;
                temp = dis[j] + it.second;
                if (dis[it.first] > temp) {
                    dis[it.first] = temp;
                    check = true;
                    pi[it.first] = j;
                }
            }
        }
        if (!check) break;
    }
    if (dis[t] == INF) return false;
    int loc = t;
    while (loc != s) {
        int index = 0;
        for (auto &it : edges[pi[loc]]) {
            if (it.first == loc) {
                edges[loc].push_back({pi[loc], -it.second});
                break;
            }
            ++index;
        }
        edges[pi[loc]].erase(edges[pi[loc]].begin() + index);
        loc = pi[loc];
    }
    return true;
}

double maxMatching(vector<vector<double>> &arr, int &n, int &m) {
    int start = 0, end = m + n + 1;
    vector<vector<pair<int, double>>> adj(n + m + 2, vector<pair<int, double>>());
    for (int i = 1; i <= n; ++i)
        adj[0].push_back({i, 1});
    for (int i = n + 1; i < n + m + 1; ++i)
        adj[i].push_back({end, 1});
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            adj[i].push_back({j + n, arr[i][j]});
    int cnt = n;
    while (cnt--)
        bellman_ford(m + n + 2, start, end, adj);
    double ans = 0;
    stack<int> s;
    for (auto &it : adj[end])
        s.push(it.first);
    while (!s.empty()) {
        int t = s.top();
        s.pop();
        ans -= adj[t][0].second;
    }
    return ans / n;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    while (n && m) {
        vector<vector<double>> arr(n + 1, vector<double>(m + 1, 1));
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j)
                cin >> arr[i][j];
        cout << fixed << setprecision(2) << maxMatching(arr, n, m) + 0.0000001 << endl;
        cin >> n >> m;
    }
}
```
### $n$ is the number of bank, $m$ is the number of cruiser
## 空間複雜度分析
* $adj(n * m + n + m)$, $dis(n + m + 2)$, $pi(n + m + 2)$, $s(m)$
* $=n * m + 3 * n + 4 * m + 4$
* $O(n * m)$

## 時間複雜度分析

### Best Case && Worst Case
* 建adj $(n * m + n + m)$
* $n$次bellman
* bellman-ford $O((n + m + 1) * (n * m + n + m))$
* bellman-ford 回追路徑 $O(n * m + 1)$
* $O(n^2m(n+m))$

## DATE
2023/05/21