[Luogu2756] [网络流24题]飞行员配对方案问题

传送门

这应该是比裸的一个网络流/二分图匹配了。

直接跑一遍Dinic求出最大流。再依次遍历所有二分图上的边,如果剩余流量是0,则说明两者相互匹配,作为一组输出。

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 205
#define MAXM 20005

struct edge {
    int u,v,next,c;
}G[MAXM];

int head[MAXN],cur[MAXN];
int d[MAXN],rec[MAXM];

int N,M,S,T;
int tot = -1,cnt = 0;

inline void add(int u,int v,int c) {
    G[++tot].u = u; G[tot].v = v; G[tot].c = c;
    G[tot].next = head[u]; head[u] = tot;
}

inline bool bfs() {
    
    std::memset(d,0,sizeof(d));
    std::queue < int > q;
    d[S] = 1; q.push(S);
    
    while(!q.empty()) {
        int u = q.front(); q.pop();
        for(int i=head[u];i!=-1;i=G[i].next) {
            int v = G[i].v; 
            if(d[v]==0&&G[i].c>0) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d[T];
}

int dfs(int u,int a) {
    if(u==T) return a;
    int flow = 0,temp;
    for(int& i=cur[u];i!=-1;i=G[i].next) {
        int v = G[i].v;
        if(d[u]+1==d[v]&&G[i].c&&(temp = dfs(v,std::min(a,G[i].c)))>0) {
            flow += temp; a -= temp; 
            G[i].c -= temp; G[i^1].c += temp;
            if(a==0) break;
        }
    }
    return flow;
}

inline int dinic() {
    
    int flow = 0;
    for(int i=1;i<=N;++i) {
        add(S,i,1); add(i,S,0);
    }
    for(int i=N+1;i<=M;++i) {
        add(i,T,1); add(T,i,0);
    }
    
    while(bfs()) {
        for(int i=1;i<=M+2;++i) cur[i] = head[i];
        flow += dfs(S,2147483647);
    }
    return flow;
}

int main() {
    
    int u = 0,v = 0;
    scanf("%d%d",&N,&M);
    std::memset(head,-1,sizeof(head));
    
    while(scanf("%d%d",&u,&v)&&(u!=-1)&&(v!=-1)) {
        add(u,v,1); add(v,u,0);
        rec[++cnt] = tot - 1 ;
    }
    
    S = M + 1; T = S + 1;
    int temp = dinic();
    
    if(temp) {
        printf("%d\n",temp);
        for(int i=1;i<=cnt;++i) {
            if(G[rec[i]].c==0) printf("%d %d\n",G[rec[i]].u,G[rec[i]].v);
        }
    }
    else puts("No Solution!");
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Neworld2002/p/10225656.html