zoukankan      html  css  js  c++  java
  • [网络流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;
    }
  • 相关阅读:
    mysql 中文字段排序( UTF8按拼音首字母排序)
    输入输出挂
    HDU 6301 贪心
    HDU1533 最小费用最大流
    POJ 2135 最小费用最大流 入门题
    HDU 6278 主席树(区间第k大)+二分
    HDU3549 最大流 裸题
    2018牛客网暑期ACM多校训练营(第一场)D图同构,J
    POJ 1804 逆序对数量 / 归并排序
    Codeforces Round #489 (Div. 2) B、C
  • 原文地址:https://www.cnblogs.com/AireenYe/p/6235505.html
Copyright © 2011-2022 走看看