The problem of matching scheme of P2756 pilot in Luogu

Keywords: C++ Programming network

Full name: linear programming and network flow 24 questions

In order of difficulty:

1. Pilot pairing scheme problem (find the maximum number of matches and output the pairing scheme)

There are two approaches:

1) the Hungarian algorithm of bipartite graph matching can directly find the maximum matching number, and the best matching scheme is recorded in the array

2) maximum flow: edge building from super source point S to each element in set A (capacity: 1), edge building from each point in set B to sink point (capacity: 1), edge building between matching points in set A and set B (capacity: 1), running the maximum flow can get the maximum matching number

Because the used traffic in Dinic algorithm will be reduced, and its reverse side traffic will be increased

So if two points in the AB set are matched, the edge capacity of a - > b is 0 (or the edge capacity of B - > A is 1)

 

Binary Hungarian version:

#include <bits/stdc++.h>
using namespace std;
#define N 105
#define M 20005
struct Edge{
    int to,next;
}edge[M];
int n,m;
int vis[N],match[N],to[N],head[N];//Initialize match - > 1, to - > 0
int cnt;
void init(){
    cnt = 0;
    memset(head,-1,sizeof(head));
    memset(match,-1,sizeof(match));
    memset(to,0,sizeof(to));
}

bool dfs(int u){
    for(int i = head[u];i != -1;i = edge[i].next){
        int v = edge[i].to;
        if(!vis[v]){
            vis[v] = 1;
            if(match[v] == -1 || dfs(match[v])){
                match[v] = u;
                to[u] = v;
                return true;
            }
        }
    }
    return false;
}
//cnt is the maximum number of matching points (single side points)
int hungry(){
    cnt = 0;
    for(int i = 1;i <= n;++i){
        memset(vis,0,sizeof(vis));
        if(!to[i]) cnt += dfs(i);
    }
    return cnt;
}

int main()
{
    init();
    scanf("%d%d",&m,&n);
    int u,v;
    while(scanf("%d%d",&u,&v) && u != -1){
        edge[cnt].to = v,edge[cnt].next = head[u],head[u] = cnt++;
    }
    printf("%d\n",hungry());
    
    for(int i = 1;i <= m;++i)
        if(to[i]) printf("%d %d\n",i,to[i]);
    return 0;
}

 

Maximum streaming dinic version:

//Dinic algorithm of maximum flow
//m is the number of sides, n is the number of points
//Complexity O(m*n*n)
#include <bits/stdc++.h>
using namespace std;
#define N 105
#define M 20005
int INF = 0x3f3f3f3f;
int dep[N],head[N];
int to[N];//Current arc optimization
int n,m;
struct Edge{
    int to,next,w;
}edge[M<<1];
int cnt = 0;
//The reverse side of edge[i] is edge[i ^ 1]

int s,t;//S - > source, T - > sink

void ad(int x,int y,int w){
    edge[cnt].to = y,edge[cnt].next = head[x],edge[cnt].w = w,head[x] = cnt++;
    edge[cnt].to = x,edge[cnt].next = head[y],edge[cnt].w = 0,head[y] = cnt++;
}
void init(){
    memset(to,0,sizeof(to));
    memset(head,-1,sizeof(head));
    cnt = 0;
}

bool D_bfs(){
    memset(dep,0,sizeof(dep));
    memset(to,0,sizeof(to));
    dep[s] = 1;
    queue<int> Q;
    while(!Q.empty()) Q.pop();
    Q.push(s);
    while(!Q.empty()){
        int u = Q.front();
        Q.pop();
        for(int i = head[u];i != -1;i = edge[i].next){
            int v = edge[i].to;
            if(edge[i].w > 0 && !dep[v]){
                dep[v] = dep[u] + 1;
                Q.push(v);
            }
        }
    }
    if(dep[t]) return 1;
    return 0;
}

int D_dfs(int u,int now){
    if(u == t) return now;
    int beg = to[u] ? to[u] : head[u];
    for(int i = beg;i != -1;i = edge[i].next){
        int v = edge[i].to;
        if(dep[v] == dep[u] + 1 && edge[i].w > 0){
            int di = D_dfs(v,min(now,edge[i].w));
            if(di == 0) continue;
            edge[i].w -= di;
            edge[i^1].w += di;
            if(edge[i].w) to[u] = i;
            else to[u] = edge[i].next;
            return di;
        }
    }
    return 0;
}

int Dinic(){
    int sum = 0,flow;
    while(D_bfs()){
        while((flow = D_dfs(s,INF)))
            sum += flow;
    }
    return sum;
}
int l , r;
void getMap(){
    scanf("%d%d",&m,&n);
    s = 0,t = n+1;
    for(int i = 1;i <= m;++i) ad(0,i,1);
    for(int i = m+1;i <= n;++i) ad(i,n+1,1);
    int u,v;
    l = cnt;
    while(scanf("%d%d",&u,&v) && u != -1) ad(u,v,1);
    r = cnt;
}

int main()
{
    init();
    getMap();
    printf("%d\n",Dinic());
    for(int i = l;i < r;i += 2){
        if(edge[i].w == 0){
            printf("%d %d\n",edge[i^1].to,edge[i].to);
        }
    }
    return 0;
}

Posted by yuraupt on Wed, 01 Jan 2020 00:26:04 -0800