zoukankan      html  css  js  c++  java
  • 【题解】Uoj79一般图最大匹配

      带花树裸题,感觉带花树强强……不会的勿看此文,解释的可能不对,只是给自己看的!!!如题,带花树即为求一般图最大匹配算法(匈牙利与dinic为二分图最大匹配)。推荐论文:2015年《浅谈图的匹配算法及其应用》(长郡中学    ——陈胤伯)。论文当中有对于带花树算法的详细解析,在这里只想记录一下算法的基本流程:

    ——————————————————————————

      (id) : 记录一个点为奇点/偶点(0偶1奇)。

      (fa) : 并查集记录一个点属于哪一个点为根的花。

    ——————————————————————————

      我们对于每一个没有匹配到的点进行 bfs,默认该点为一个偶点。

      当我们遍历到一个未访问过的点(在此次bfs中):

        -若该点未匹配:

        Yes!我们找到了一条新的增广路。顺着 ( pre ) 数组的指引反向增广,修改匹配的对象。(当前点为(x), (y = pre[x]),(z = match[y]), 则应使 (x), (y) 成为匹配边,(z) 点继续增广(过程同上,一直到增广不下去了为止))。

        -若该点已匹配:

        将它的匹配点标记为偶点,推进队列。

      遍历到一个访问过的点(在此次bfs中):

        -若该点是一个奇点:

        找到的是一个偶环,无视。

        -若该点是一个偶点:

        如果这两个点本来就在同一朵花中,无视。否则进行缩花。我们找到这两点在bfs树上的 lca: (k);将这两点之间连上边从(x) 开始向上遍历所有的匹配边,找到一朵花的根节点就修改其花根为 (k); 若找到的点有匹配点,则将匹配点也标记为偶点并压入队列。

      总之是个玄学算法……

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 300000
    int n, m, match[maxn];
    int pre[maxn], id[maxn];
    int timer, fa[maxn], ans;
    int vis[maxn];
    queue <int> q;
    
    struct edge
    {
        int cnp = 1, head[maxn], to[maxn], last[maxn];
        void add(int u, int v)
        {
            to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
            to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
        }
    }E1;
    
    int read()
    {
        int x = 0, k = 1;
        char c;
        c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
    
    void Clear(queue<int> &q) {
        queue <int> empty;
        swap(empty, q);
    }
    
    int LCA(int x, int y)
    {
        timer ++;
        while(vis[x] != timer) 
        {
            if(x)
            {
                x = find(x);
                if(vis[x] == timer) return x;
                vis[x] = timer;
                if(match[x]) x = find(pre[match[x]]);
                else x = 0;
            }
            swap(x, y);
        }
        return x;
    }
    
    void Change(int x, int y, int k)
    {
        while(find(x) != k)
        {
            pre[x] = y; int z = match[x];
            if(id[z] == 1) id[z] = 0, q.push(z);
            if(find(z) == z) fa[z] = k;
            if(find(x) == x) fa[x] = k;
            y = z; x = pre[y];
        }
    }
    
    bool bfs(int u)
    {
        for(int i = 1; i <= n; i ++) id[i] = -1, fa[i] = i;
        Clear(q); q.push(u); id[u] = 0;
        while(!q.empty())
        {
            int u = q.front(); q.pop();
            for(int i = E1.head[u]; i; i = E1.last[i])
            {
                int v = E1.to[i];
                if(id[v] == -1)
                {
                    pre[v] = u; id[v] = 1;
                    if(match[v])
                    {
                        id[match[v]] = 0; q.push(match[v]);
                        continue;
                    }
                    int last, t, now = v;
                    while(now)
                    {
                        t = pre[now]; last = match[t];
                        match[t] = now, match[now] = t;
                        now = last;
                    }
                    return 1;
                }
                else if(!id[v] && find(u) != find(v))
                {
                    int lca = LCA(u, v);
                    Change(u, v, lca), Change(v, u, lca);
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        n = read(), m = read();
        for(int i = 1; i <= m; i ++)
        {
            int x = read(), y = read();
            E1.add(x, y);
        }
        for(int i = 1; i <= n; i ++) if(!match[i] && bfs(i)) ans ++;
        printf("%d
    ", ans);
        for(int i = 1; i <= n; i ++) printf("%d ", match[i]);
        return 0;
    }
  • 相关阅读:
    iOS学习笔记(六)——ViewController
    IOS学习笔记(五)——UI基础UIWindow、UIView
    iOS学习笔记(四)——iOS应用程序生命周期
    iOS学习笔记(三)——iOS系统架构
    iOS学习笔记(二)——Hello iOS
    iOS学习笔记(一)——ios搭建开发环境
    Android UI开发第三十篇——使用Fragment构建灵活的桌面
    android实现卸载提示
    Android UI开发第二十六篇——Fragment间的通信
    Android UI开发第二十九篇——Android中五种常用的menu(菜单)
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9244779.html
Copyright © 2011-2022 走看看