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;
    }
  • 相关阅读:
    mouse_event模拟鼠标滚轮
    润乾报表配置技术路线
    建筑 物件 开心背单词 读句子,单词,字母,看图例, 翻译,看动画
    文字过渡动画,曲线过渡动画,,使用这个插件assign shape keys
    运动锻炼 开心背单词 读句子,单词,字母,看图例, 翻译,看动画,学英语,轻松背单词,简单背单词
    blender293 内置插件 精度绘画控件,PDT学习003,pdt tangents 切线
    日常用品 背单词 读句子 看图片 读单词 读字母 翻译, 看动画 学英语
    blender293 内置插件 精度绘画控件,PDT学习 precision drawing tools
    乔布斯 背单词 02 读句子 单词 字母 翻译,看动画 学英语 名言 我菜顾我在,我菜故我在,blender加python
    狐狸 和 乌鸦 英语 朗读句子 背单词
  • 原文地址:https://www.cnblogs.com/AireenYe/p/6235505.html
Copyright © 2011-2022 走看看