• Hungarian Algorithm


    https://www.renfei.org/blog/bipartite-matching.html
    https://en.wikipedia.org/wiki/Matching_(graph_theory)

    Hungarian Algorithm

    Given a matching M,

    • an alternating path is a path that begins with an unmatched vertex and whose edges belong alternately to the matching and not to the matching.
    • an augmenting path is an alternating path that starts from and ends on free (unmatched) vertices.

    Traverse all the points on the left, for each point (u) if we can find a augmenting path (vec{p}) starting from (u), then we use the edges of (vec{p}) to update the matches of each point on (vec{p}).

    Problems

    HDU 1068 Girls and Boys

    This problem is to figure out the number of maximum independent set of bipartite graph.

    #include <bits/stdc++.h>
    #define DBG(x) cerr << #x << " = " << x << endl
    
    using namespace std;
    typedef long long LL;
    
    const int MAXN = 1024;
    
    vector<int> g[MAXN];
    int match[MAXN];
    bool vis[MAXN];
    
    void init(int n) {
        for (int i = 0; i < n; i++) {
            g[i].clear();
        }
        fill(match, match + n, -1);
    }
    
    bool dfs(int u) {
        for (auto v : g[u]) {
            if (vis[v]) continue;
            vis[v] = true;
            if (match[v] == -1 || dfs(match[v])) {
                match[v] = u;
                return true;
            }
        }
    
        return false;
    }
    
    int hungary(int n) {
        int ans = 0;
        for (int i = 0; i < n; i++) {
            fill(vis, vis + n, false);
            if (dfs(i)) ans++;
        }
        return ans / 2;
    }
    
    int main(int argc, char **argv) {
        int n;
        while (scanf("%d", &n) != EOF) {
            init(n);
            for (int i = 0; i < n; i++) {
                int u, cnt;
                scanf("%d: (%d) ", &u, &cnt);
                for (int j = 0; j < cnt; j++) {
                    int v;
                    scanf("%d", &v);
                    g[u].push_back(v);
                }
            }
            printf("%d
    ", n - hungary(n));
        }
        return 0;
    }
    

    HDU 1179 Ollivanders: Makers of Fine Wands since 382 BC.

    There are 3 ways to solve the problem.

    #include <bits/stdc++.h>
    #define DBG(x) cerr << #x << " = " << x << endl
    
    using namespace std;
    typedef long long LL;
    
    const int MAXN = 128;
    vector<int> g[MAXN];
    int match[MAXN];
    bool vis[MAXN];
    
    void init(int n, int m) {
        for (int i = 1; i <= m; i++) {
            g[i].clear();
        }
        fill(match + 1, match + 1 + n, -1);
    }
    
    void add(int u, int v) {
        g[u].push_back(v);
    }
    
    bool dfs(int u) {
        for (auto v : g[u]) {
            if (vis[v]) continue;
            vis[v] = true;
            if (match[v] == -1 || dfs(match[v])) {
                match[v] = u;
                return true;
            }
        }
        return false;
    }
    
    int hungary(int n, int m) {
        int ans = 0;
        for (int i = 1; i <= m; i++) {
            fill(vis + 1, vis + 1 + n, false);
            if (dfs(i)) ans++;
        }
        return ans;
    }
    
    int main(int argc, char **argv) {
        int n, m;
        while (scanf("%d%d", &n, &m) != EOF) {
            init(n, m);
            for (int i = 1; i <= m; i++) {
                int c;
                scanf("%d", &c);
                for (int j = 0; j < c; j++) {
                    int v;
                    scanf("%d", &v);
                    add(i, v);
                }
            }
            printf("%d
    ", hungary(n, m));
        }
        return 0;
    }
    
    #include <bits/stdc++.h>
    #define DBG(x) cerr << #x << " = " << x << endl
    
    using namespace std;
    typedef long long LL;
    
    const int MAXN = 128 * 2;
    
    vector<int> g[MAXN];
    int match[MAXN];
    bool vis[MAXN];
    
    void add(int u, int v) {
        g[u].push_back(v);
    }
    
    void init(int n, int m) {
        for (int i = 1; i <= n + m; i++) {
            g[i].clear();
        }
        fill(match + 1, match + 1 + n, -1);
    }
    
    bool dfs(int u) {
        for (auto v : g[u]) {
            if (vis[v]) continue;
            vis[v] = true;
            if (match[v] == -1 || dfs(match[v])) {
                match[v] = u;
                return true;
            }
        }
        return false;
    }
    
    int hungarian(int n, int m) {
        int ans = 0;
        for (int u = n + 1; u <= n + m; u++) {
            fill(vis + 1, vis + 1 + n, false);
            if (dfs(u)) ans++;
        }
        return ans;
    }
    
    int main(int argc, char **argv) {
        int n, m;
        while (scanf("%d%d", &n, &m) != EOF) {
            init(n, m);
            for (int u = n + 1; u <= n + m; u++) {
                int c;
                scanf("%d", &c);
                for (int j = 0; j < c; j++) {
                    int v;
                    scanf("%d", &v);
                    add(u, v);
                    add(v, u);
                }
            }
            printf("%d
    ", hungarian(n, m));
        }
        return 0;
    }
    
    #include <bits/stdc++.h>
    #define DBG(x) cerr << #x << " = " << x << endl
    
    using namespace std;
    typedef long long LL;
    
    const int MAXN = 128 * 2;
    
    vector<int> g[MAXN];
    int match[MAXN];
    bool vis[MAXN];
    
    void init(int n, int m) {
        for (int i = 1; i <= n + m; i++) {
            g[i].clear();
        }
        fill(match + 1, match + 1 + n + m, -1);
    }
    
    bool dfs(int u) {
        for (auto v : g[u]) {
            if (vis[v]) continue;
            vis[v] = true;
            if (match[v] == -1 || dfs(match[v])) {
                match[v] = u;
                return true;
            }
        }
        return false;
    }
    
    int hungarian(int n, int m) {
        int ans = 0;
        for (int u = 1; u <= n + m; u++) {
            fill(vis + 1, vis + 1 + n + m, false);
            if (dfs(u)) ans++;
        }
        return ans / 2;
    }
    
    void add(int u, int v) {
        g[u].push_back(v);
    }
    
    int main(int argc, char **argv) {
        int n, m;
        while (scanf("%d%d", &n, &m) != EOF) {
            init(n, m);
            for (int u = n + 1; u <= n + m; u++) {
                int c;
                scanf("%d", &c);
                for (int j = 0; j < c; j++) {
                    int v;
                    scanf("%d", &v);
                    add(u, v);
                    add(v, u);
                }
            }
            printf("%d
    ", hungarian(n, m));
        }
        return 0;
    }
    
  • 相关阅读:
    重要的环境变量
    常用的转义字符
    常用系统工作命令
    栈 队列 和 双向队列
    时间
    默认值字典
    Counter
    random
    22 内置常用模块01
    super
  • 原文地址:https://www.cnblogs.com/ToRapture/p/12697650.html
Copyright © 2020-2023  润新知