• 一般图最大匹配


    先说下思想:
    一般图与二分图不同的地方就在于奇环, 考虑出现奇环如何处理, 我们发现我们从一个点搜到一个奇环时, 最先搜到的地方我们称为花基, 那么会发现从花基从逆时针, 顺时针搜到这个奇环中的某一个点u时, 会发现u被我们要求标成两种不同的颜色, 这时我们能够发现奇环, 将其缩成一个点, 可以证明缩点后不会对増广产生影响, 那么我们缩点时需要做些什么:

    • 首先, 我们用pre记录增广路上的前驱, 这样会方便我们的反边及展开花
    • 然后, 在这个花中我们用并查集来表示他们同属于一朵花
    • 花中的节点非外结点全部改成外结点(即放入队列的点), 因为花的任何一个位置都可以延伸出去, 并且花嵌花并不影响, 还有一点就是防止pre从花基或大花指向小花, 要注意判断
    • 展开时同 二分图
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 5e2 + 10;
    const int MAXM = MAXN * MAXN;
    #define debug(x) cerr << "!" << endl
    #define rep(i, s, t) for(int i = s; i <= t; ++i)
    #define erep(i, u) for(int i = Begin[u]; i ^ (-1); i = Next[i])
    
    #define C c = getchar()
    template<typename T>
    T read() {
        char C; T x = 0, f = 1;
        while(c < '0' || c > '9') f = c=='-'?-1:1, C;
        while(c >= '0' && c <= '9') x = x*10 + c-'0', C;
        return x * f;
    }
    
    int n, m, flag;
    namespace Bloosom {
        int fa[MAXN], vis[MAXN];
        int pre[MAXN], match[MAXN], color[MAXN];
        int e, Begin[MAXN], to[MAXM], Next[MAXM];
    
        void add(int x, int y) {
            to[e] = y;
            Next[e] = Begin[x];
            Begin[x] = e++;
        }
    
        int find(int x) {
            return fa[x] = x ^ fa[x]? find(fa[x]) : x;
        }
    
        queue<int> Q;
    #define FILL(a, b) memset(a, b, sizeof a)
        void init() {
            FILL(pre, 0);
            FILL(color, -1);
            rep(i, 1, n) fa[i] = i;
            while(!Q.empty()) Q.pop();
        }
    
        int Lca(int u, int v) {
            FILL(vis, 0); int lca = 0;
            for(; u; u = pre[match[u]]) u = find(u), vis[u] = 1;
            for(; v; v = pre[match[v]]) 
                {v = find(v); if(vis[v]) {lca = v; break;}}
            return lca;
        }
    
        void Union(int u, int F) {
            for(; u ^ F; u = pre[match[u]]) {
                int x = match[u], y = pre[x];
                int a = find(u), b = find(x), c = find(y);
    
                if(find(y) ^ F) pre[y] = x;
                if(color[x] == 1) color[x] = 0, Q.push(x);
                fa[a] = b; fa[b] = c;
            }
        }
    
        void contract(int x, int y) {
            int lca = Lca(x, y);
            if(find(x) ^ lca) pre[x] = y;
            if(find(y) ^ lca) pre[y] = x;
            Union(x, lca);
    //      if(flag) debug();
            Union(y, lca);
        }
    
        void BFS(int S) {
            init();
            Q.push(S); color[S] = 0;
            while(!Q.empty()) {
                int u = Q.front(); Q.pop();
                erep(i, u) {
                    int v = to[i];
                    if(match[v] == u || color[v] == 1
                    || find(u) == find(v)) continue;
    
                    if(!color[v]) {
                        //flag = (S == 11 && v == 7);
                        contract(u, v);
                    }else if(match[v]) {
                        pre[v] = u;
                        color[v] = 1;
                        color[match[v]] = 0;
                        Q.push(match[v]);
                    }else {
                        pre[v] = u;
                        int x = u, y = v;
                        for(;y;) {
                            int Nexty = match[x], Nextx = pre[Nexty];
                            match[y] = x, match[x] = y;
                            x = Nextx, y = Nexty;
                        }
                        return ;
                    }
                }
            }
        }
    };
    using namespace Bloosom;
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("input.in", "r", stdin);
        freopen("res.out", "w", stdout);
    #endif
        FILL(Begin, -1);
        n = read<int>(), m = read<int>();
        rep(i, 1, m) {
            int u = read<int>(), v = read<int>();
            add(u, v), add(v, u);
        }
    
        int Ans = 0;
        rep(i, 1, n) if(!match[i]) BFS(i);
        rep(i, 1, n) Ans += (bool) match[i];
    
        printf("%d
    ", Ans/2);
        rep(i, 1, n) printf("%d%c", match[i], i ^ n? ' ' : '
    ');
        return 0;
    }
  • 相关阅读:
    jmeter怎么衡量tps的值
    QPS、TPS、并发用户数、吞吐量关系
    PPAPI插件开发指南
    WebRTC手记之WebRtcVideoEngine2模块
    WebRTC手记Channel概念
    WebRTC手记之本地音频采集
    WebRTC手记之本地视频采集
    WebRTC手记之框架与接口
    WebRTC手记之初探
    Chromium的GPU进程启动流程
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8530149.html
Copyright © 2020-2023  润新知