zoukankan      html  css  js  c++  java
  • 飞行员配对方案问题

    题目背景

    第二次世界大战时期..

    题目描述

    英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    输入输出格式

    输入格式:

    第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行员总数(n<100);m 是外籍飞行员数。外籍飞行员编号为 1~m;英国飞行员编号为 m+1~n。

    接下来每行有 2 个正整数 i 和 j,表示外籍飞行员 i 可以和英国飞行员 j 配合。最后以 2个-1 结束。

    输出格式:

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

    输入输出样例

    输入样例#1:
    5 10
    1 7
    1 8
    2 6
    2 9
    2 10
    3 7
    3 8
    4 7
    4 8
    5 10
    -1 -1
    输出样例#1:
    4
    1 7
    2 9
    3 8
    5 10 
    思路:网络流
    代码实现:
     1 #include<cstdio>
     2 #include<cstring>
     3 int n,m,ans,cp[110];
     4 int a,b,c;
     5 int h[110],hs;
     6 struct edge{int s,n,v,r;}e[12100];
     7 int head,tail,d[110];
     8 struct queue{int s,d;}q[110];
     9 int min(int x,int y){return x<y?x:y;}
    10 bool bfs(int s,int t){
    11     memset(d,0,sizeof(d));
    12     head=tail=0;
    13     q[head++]=(queue){s,1},d[s]=1;
    14     while(head>tail){
    15         a=q[tail].s,b=q[tail++].d;
    16         for(int i=h[a];i;i=e[i].n) if(!d[e[i].s]&&e[i].v){
    17             q[head++]=(queue){e[i].s,b+1};
    18             d[e[i].s]=b+1;
    19             if(e[i].s==t) return true;
    20         }
    21     }
    22     return false;
    23 }
    24 int ap(int k,int t,int v){
    25     if(!v||k==t) return v;
    26     int act=0;
    27     for(int i=h[k];i;i=e[i].n) if(e[i].v&&d[e[i].s]==d[k]+1){
    28         int ret=ap(e[i].s,t,min(v-act,e[i].v));
    29         if(ret){
    30             e[i].v-=ret,e[e[i].r].v+=ret,act+=ret;
    31             if(k>0&&k<=m&&e[i].s>m&&e[i].s<=n) cp[k]=e[i].s;
    32         }
    33     }
    34     return act;
    35 }
    36 bool Dinic(int s,int t){
    37     if(!bfs(s,t)) return 0;
    38     ans+=ap(s,t,m);
    39 }
    40 int main(){
    41     scanf("%d%d",&m,&n);
    42     while(scanf("%d%d",&a,&b)!=EOF){
    43         if(a==-1&&b==-1) break;
    44         e[++hs]=(edge){b,h[a],1,hs+1},h[a]=hs;
    45         e[++hs]=(edge){a,h[b],0,hs-1},h[b]=hs;
    46     }
    47     for(int i=1;i<=m;i++) e[++hs]=(edge){i,h[0],1},h[0]=hs;
    48     for(int i=m+1;i<=n;i++) e[++hs]=(edge){n+1,h[i],1},h[i]=hs;
    49     while(Dinic(0,n+1));
    50     printf("%d
    ",ans);
    51     for(int i=1;i<=n;i++) if(cp[i]) printf("%d %d
    ",i,cp[i]);
    52     return 0;
    53 } 

    一个小发现,用网络流做二分图匹配不需要给源点s和汇点t引出的边建反边,有心人可以尝试证明一下。

    另外,不要尝试codevs上的,评测方法有坑,除非特定顺序才行。

    题目来源:洛谷

  • 相关阅读:
    notepad++ 编辑器链接地址可点击
    window的cmd窗口运行git
    php update for mac
    sublime打开文件时自动生成并打开.dump文件
    不能设置sublime text 2 为默认编辑器
    sublime text 2 配置文件
    Compass被墙后如何安装安装
    everything搜索工具小技巧
    Ubuntu安装已经下载好的文件包
    Flutter 异步Future与FutureBuilder实用技巧
  • 原文地址:https://www.cnblogs.com/J-william/p/6504801.html
Copyright © 2011-2022 走看看