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

Description

第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的$2$名飞行员, 其中$1$名是英国飞行员,另$1$名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。对于给定的外籍飞行员与英国飞行员的配合情况,求一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

Input

第$1$行有$2$个正整数$m$和$n$。$n$是皇家空军的飞行员总数,$m$是外籍飞行员数。外籍飞行员编号为$1;-;m$;英国飞行员编号为$m+1;-;n$。
接下来每行有$2$个正整数$i,j$,表示外籍飞行员$i$可以和英国飞行员$j$配合。文件最后以$2$个$-1$结束。

Output

第$1$行是最佳飞行员配对方案一次能派出的最多的飞机数$M$。接下来$M$行是最佳飞行员配对方案。每行有$2$个正整数$i,j$,表示在最佳飞行员配对方案中,外籍飞行员$i$和英国飞行员$j$配对。
如果所求的最佳飞行员配对方案不存在,则输出‘$No Solution!$’。

Sample Input

5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1

Sample Output

4
1 7
2 9
3 8
5 10

HINT

$n<100$.

Solution

二分图匹配.

源点向外籍飞行员连一条容量为$1$的有向边,

能配对的外籍飞行员向英国飞行员连一条容量为$1$的有向边,

英国飞行员向汇点连一条容量为$1$的有向边,

跑最大流.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 105
using namespace std;
struct graph{
    int nxt,to,f;
}e[N*N];
int g[N],dep[N],fr[N],n,m,s,t,ans,cnt=1;
queue<int> q; 
inline void addedge(int x,int y,int f){
    e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].f=f;
}
inline void adde(int x,int y,int f){
    addedge(x,y,f);addedge(y,x,0);
}
inline int bfs(int u){
    memset(dep,0,sizeof(dep));
    q.push(u);dep[u]=1;
    while(!q.empty()){
        u=q.front();q.pop();
        for(int i=g[u];i;i=e[i].nxt)
            if(e[i].f>0&&!dep[e[i].to]){
                q.push(e[i].to);
                dep[e[i].to]=dep[u]+1;
            }
    }
    return dep[t];
}
inline int dfs(int u,int f){
    int ret=0;
    if(u==t) return f;
    for(int i=g[u],fl;i&&f;i=e[i].nxt)
        if(e[i].f>0&&dep[e[i].to]==dep[u]+1){
            fl=dfs(e[i].to,min(f,e[i].f));
            f-=fl;ret+=fl;e[i].f-=fl;e[i^1].f+=fl;
            if(fl){
                if(u<=m&&e[i].to!=s)
                    fr[e[i].to]=u;
                else if(e[i].to<=m&&u!=s)
                    fr[e[i].to]=0; 
            }
        }
    return ret;
}
inline int dinic(){
    int ret=0;
    while(true){
        if(!bfs(s)) return ret;
        ret+=dfs(s,N);
    }
}
inline void Aireen(){
    scanf("%d%d",&m,&n);
    for(int j,k;;){
        scanf("%d%d",&j,&k);
        if(j<0) break;
        adde(j,k,1);
    }
    s=n+1;t=s+1; 
    for(int i=1;i<=m;++i)
        adde(s,i,1);
    for(int i=m+1;i<=n;++i)
        adde(i,t,1);
    ans=dinic();
    if(ans){
        printf("%d
",ans);
        for(int i=m+1;i<=n;++i)
            if(fr[i]) printf("%d %d
",fr[i],i);
    }
    else puts("No Solution!");
}
int main(){
    freopen("air.in","r",stdin);
    freopen("air.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}
输方案不给我$spj…$,我只好自己写一个 一个一个测试点手动测试$QAQ$
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 105
using namespace std;
char s1[N],s2[N];
int n,m;
bool a[N][N],b[N];
int main(){
    freopen("air9.in","r",stdin);
    scanf("%d%d",&m,&n);
    for(int j,k;;){
        scanf("%d%d",&j,&k);
        if(j<0) break;
        a[j][k]=true;
    }
    freopen("air9.out","r",stdin);
    scanf("%s",s1);
    freopen("air.out","r",stdin);
    scanf("%s",s2);
    if(strcmp(s1,s2)){
        puts("No");return 0;
    }
    m=0;
    for(int i=0;s1[i];++i)
        m=m*10+s1[i]-'0';
    int j,k;
    while(scanf("%d%d",&j,&k)==2){
        scanf("%d%d",&j,&k);
        if(b[j]||b[j]||!a[j][k]){
            puts("No");return 0;
        }
        b[j]=b[k]=true;
    }
    puts("YES");
    fclose(stdin);
    return 0;
}
原文地址:https://www.cnblogs.com/AireenYe/p/6235505.html