网络流二十四题之一 —— 飞行员配对方案问题(AIR)

注:本题在Codevs上有原题,但因为缺少Special Judge而无法通过。请想要数据的Oier通过邮箱联系我(邮箱请见左上角)。

飞行员配对方案问题

Description

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

Input

由文件 input.txt 提供输入数据。
文件第 1 行有 2 个正整数 m n
n 是皇家空军的飞行员总数 (n<100) m 是外籍飞行员数。
外籍飞行员编号为 1 ~ m ;英国飞行员编号为 m+1 ~ n
接下来每行有 2 个正整数 i j ,表示外籍飞行员 i 可以和英国飞行员 j 配合。
文件最后以 2 1 结束。

Output

程序运行结束时,将最佳飞行员配对方案输出到文件 output.txt 中。
1 行是最佳飞行员配对方案一次能派出的最多的飞机数 M
接下来 M 行是最佳飞行员配对方案。
每行有 2 个正整数 i j ,表示在最佳飞行员配对方案中,飞行员 i 和飞行员 j 配对。
如果所求的最佳飞行员配对方案不存在,则输出“ NoSolution!

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

Solution

本题就是一个典型的二分图最大匹配问题,可以当作最大流问题来解决。
我给出的求最大流的代码是 Dinic 算法(输出方案的部分我图省事,打得比较丑)。

[cpp]
  1. #include <iostream>  
  2. #include <cstring>  
  3. #include <cstdio>  
  4. #include <queue>  
  5. #include <algorithm>  
  6.   
  7. #define Min(a,b) ((a)<(b)?(a):(b))  
  8.   
  9. using namespace std;  
  10.   
  11. struct ans{  
  12.     int a,b;  
  13. }ANS[1000];  
  14.   
  15. bool cmp(ans a,ans b){  
  16.     return a.a<b.a||(a.a==b.a&&a.b<b.b);  
  17. }  
  18.   
  19. const int INF=0x3f3f3f3f;  
  20. const int MAXN=10000;  
  21.   
  22. queue<int>q;  
  23. int data[MAXN*2],weight[MAXN*2];  
  24. int nxt[MAXN*2],head[MAXN],dis[MAXN],from[MAXN*2];  
  25. int n,m,cnt,s,t,ANSS;  
  26.   
  27. void add(int x,int y,int z){  
  28.     from[cnt]=x;nxt[cnt]=head[x];data[cnt]=y;weight[cnt]=z;head[x]=cnt++;  
  29.     from[cnt]=y;nxt[cnt]=head[y];data[cnt]=x;weight[cnt]=0;head[y]=cnt++;   
  30. }  
  31.   
  32. bool BFS(){  
  33.     memset(dis,-1,sizeof dis);  
  34.     dis[s]=0;  
  35.     q.push(s);  
  36.     while(!q.empty()){  
  37.         int now=q.front();  
  38.         q.pop();  
  39.         for(int i=head[now];i!=-1;i=nxt[i])if(dis[data[i]]<0&&weight[i]){  
  40.             dis[data[i]]=dis[now]+1;  
  41.             q.push(data[i]);  
  42.         }  
  43.     }  
  44.     return dis[t]>0;  
  45. }  
  46.   
  47. int dfs(int now,int low){  
  48.     if(now==t)return low;  
  49.     int Low;  
  50.     for(int i=head[now];i!=-1;i=nxt[i]){  
  51.         if(weight[i]&&dis[data[i]]==dis[now]+1){  
  52.             if(Low=dfs(data[i],Min(low,weight[i]))){  
  53.                 weight[i]-=Low;  
  54.                 weight[i^1]+=Low;  
  55.                 return Low;  
  56.             }  
  57.         }  
  58.     }  
  59.     return 0;  
  60. }  
  61.   
  62. int main(){  
  63.     freopen(”air.in”,“r”,stdin);  
  64.     freopen(”air.out”,“w”,stdout);  
  65.     memset(head,-1,sizeof head);  
  66.     scanf(”%d%d”,&m,&n);  
  67. //  s=1;t=n;  
  68. //  for(int i=1;i<=m;i++){  
  69. //      int x,y,z;  
  70. //      scanf(“%d%d%d”,&x,&y,&z);  
  71. //      add(x,y,z);  
  72. //  }  
  73.     s=100*4;  
  74.     t=100*4+1;  
  75.     int x,y;  
  76.     while(scanf(“%d%d”,&x,&y)!=EOF&&(x!=-1||y!=-1))add(x,y+n-m,1);  
  77.     for(int i=m+1;i<=n;i++){  
  78.         add(i+n-m,i,1);  
  79.         add(i,t,1);  
  80.     }  
  81.     for(int i=1;i<=m;i++)add(s,i,1);  
  82.     int sum=0,flow;  
  83.     while(BFS())  
  84.         while(flow=dfs(s,INF))sum+=flow;  
  85.     if(!sum){  
  86.         printf(”No Solution!”);  
  87.         return 0;  
  88.     }  
  89.     printf(”%d\n”,sum);  
  90.     for(int i=0;i<cnt;i++){  
  91.         if(!weight[i]&&from[i]!=s&&data[i]!=t&&from[i]!=t&&data[i]!=s&&from[i]<data[i]-n+m){  
  92.             ANS[++ANSS].a=from[i];  
  93.             ANS[ANSS].b=data[i]-n+m;  
  94.         }  
  95.     }  
  96.     sort(ANS+1,ANS+ANSS+1,cmp);  
  97.     for(int i=1;i<=ANSS;i++)printf(“%d %d\n”,ANS[i].a,ANS[i].b);  
  98.     return 0;  
  99. }  

你可能感兴趣的:(网络流二十四题之一 —— 飞行员配对方案问题(AIR))