zoukankan      html  css  js  c++  java
  • 二分图最大匹配模版 m√(n) 复杂度

    周大爷在比赛中搜到的黑科技二分图模版,复杂度为m√(n):

    注意:点的序号要从0开始!

    需要把nx,ny都赋值为n(点数)

    const int MAXN = 1010;
    const int MAXM = 1010*1010;
    
    struct Edge {
        int v;
        int next;
    } edge[MAXM];
    
    struct node {
        double x, y;
        double v;
    } a[MAXN], b[MAXN];
    
    int nx, ny;
    int cnt;
    int t;
    int dis;
    
    
    int first[MAXN];
    int xlink[MAXN], ylink[MAXN];
    /*xlink[i]表示左集合顶点所匹配的右集合顶点序号,ylink[i]表示右集合i顶点匹配到的左集合顶点序号。*/
    int dx[MAXN], dy[MAXN];
    /*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号*/
    int vis[MAXN]; //寻找增广路的标记数组
    
    void init() {
        cnt = 0;
        memset(first, -1, sizeof(first));
        memset(xlink, -1, sizeof(xlink));
        memset(ylink, -1, sizeof(ylink));
    }
    
    void read_graph(int u, int v) {
        edge[cnt].v = v;
        edge[cnt].next = first[u], first[u] = cnt++;
    }
    
    int bfs() {
        queue<int> q;
        dis = INF;
        memset(dx, -1, sizeof(dx));
        memset(dy, -1, sizeof(dy));
        for(int i = 0; i < nx; i++) {
            if(xlink[i] == -1) {
                q.push(i);
                dx[i] = 0;
            }
        }
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            if(dx[u] > dis) break;
            for(int e = first[u]; e != -1; e = edge[e].next) {
                int v = edge[e].v;
                if(dy[v] == -1) {
                    dy[v] = dx[u] + 1;
                    if(ylink[v] == -1) dis = dy[v];
                    else {
                        dx[ylink[v]] = dy[v]+1;
                        q.push(ylink[v]);
                    }
                }
            }
        }
        return dis != INF;
    }
    
    int find(int u) {
        for(int e = first[u]; e != -1; e = edge[e].next) {
            int v = edge[e].v;
            if(!vis[v] && dy[v] == dx[u]+1) {
                vis[v] = 1;
                if(ylink[v] != -1 && dy[v] == dis) continue;
                if(ylink[v] == -1 || find(ylink[v])) {
                    xlink[u] = v, ylink[v] = u;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int MaxMatch() {
        int ans = 0;
        while(bfs()) {
            memset(vis, 0, sizeof(vis));
            for(int i = 0; i < nx; i++) if(xlink[i] == -1) {
                    ans += find(i);
                }
        }
        return ans;
    }
    
    double dist(const node a, const node b) {
        return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
    }

    调用:

    init();
    for(int i = 0; i < m; i++) {
        if(l[edgee[i][0]] && edgee[i][1] != s && !l[edgee[i][1]])    read_graph(edgee[i][0],edgee[i][1]);
        if(l[edgee[i][1]] && edgee[i][0] != s && !l[edgee[i][0]])    read_graph(edgee[i][1],edgee[i][0]);
    }
    nx = n;
    ny = n;
    int ans = MaxMatch();
  • 相关阅读:
    Lucene:(一)建立索引文件:2。建立索引文件(一)
    Lucene:(一)建立索引文件:2。建立索引文件(二)Segment文件
    92.外边距设置 Walker
    99.元素居中及样式重置 Walker
    94.外边距踩坑 Walker
    101.列表属性 Walker
    97.boxsizing属性 Walker
    98.溢出隐藏 Walker
    95.内边距设置 Walker
    96.内边距和边框踩坑 Walker
  • 原文地址:https://www.cnblogs.com/zinyy/p/9385370.html
Copyright © 2011-2022 走看看