• [网络流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;
    }
  • 相关阅读:
    HDU5470 Typewriter SAM 动态规划 单调队列
    BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树
    Codeforces 235C Cyclical Quest 字符串 SAM KMP
    HDU4622 Reincarnation 字符串 SAM
    Codeforces 452E Three strings 字符串 SAM
    BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 字符串 SAM
    2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他
    2018牛客网暑假ACM多校训练赛(第三场)G Coloring Tree 计数,bfs
    2018牛客网暑假ACM多校训练赛(第三场)D Encrypted String Matching 多项式 FFT
    UOJ#310 【UNR #2】黎明前的巧克力 FWT 多项式
  • 原文地址:https://www.cnblogs.com/AireenYe/p/6235505.html
Copyright © 2020-2023  润新知