网络流基本知识就不在这里阐述了

    算法实现题 8-1 飞行员配对方案问题



  问题描述:
      第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出
    的每一架飞机都需要配备在航行技能和语言上能互相配合的 2 名飞行员, 其中 1 名是英国飞
    行员,另 1 名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英
    国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的
    外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空
    军一次能派出最多的飞机。
  编程任务:
      对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,
    使皇家空军一次能派出最多的飞机。
  数据输入:
      由文件 input.txt 提供输入数据。文件第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行
    员总数(n<100);m 是外籍飞行员数。外籍飞行员编号为 1~m;英国飞行员编号为 m+1~n。
    接下来每行有 2 个正整数 i 和 j,表示外籍飞行员 i 可以和英国飞行员 j 配合。文件最后以 2
    个-1 结束。
  结果输出:
      程序运行结束时,将最佳飞行员配对方案输出到文件 output.txt 中。第 1 行是最佳飞行
    员配对方案一次能派出的最多的飞机数 M。接下来 M 行是最佳飞行员配对方案。每行有 2
    个正整数 i 和 j,表示在最佳飞行员配对方案中,飞行员 i 和飞行员 j 配对。
    如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’ 。


  我们先画个图~网络流24题 (一)

  我们发现这题就是求二分图的最大匹配?

  好吧,你有两个选择 

  1.敲KM

  2.外籍飞行员放在x集合里面,英国王牌飞行员放在y集合里面,设立源点S,汇点T,S向每个x集合里面的点连一条容量为1的边(限制每个点只能连出一条边),y集合里面每个点连一条容量为1的点到T,每个配对连容量为1的边,跑最大流。

  网络流第一个建模。。还体验了一把输出方案的可怕之处。(从此立下没有SPJ || 唯一解 不打方案的flag!)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<queue>
 6 
 7 #define maxn 102
 8 
 9 using namespace std;
10 
11 int dis[maxn],dp[maxn][maxn],m;
12 
13 bool DFS()
14 {
15     memset(dis,-1,sizeof(dis));
16     dis[0]=1;
17     queue<int>q;
18     q.push(0);
19     while(!q.empty())
20     {
21         int u=q.front();
22         if(u==m+1)break;
23         q.pop();
24         for(int i=0;i<=m+1;i++)if(dis[i]==-1&&dp[u][i]>0){
25             dis[i]=dis[u]+1;
26             q.push(i);
27         }
28     }
29     if(dis[m]==-1)return 0;
30     else return 1;
31 }
32 
33 int find(int poi,int low)
34 {
35     int a;
36     if(poi==m+1)return low;
37     for(int i=0;i<=m+1;i++)if(dp[poi][i]>0&&dis[i]==dis[poi]+1){
38         a=find(i,min(low,dp[poi][i]));
39         if(a){
40             dp[poi][i]-=a;
41             dp[i][poi]+=a;
42             return a;
43         }
44     }
45     return 0;
46 }
47 
48 int main()
49 {
50     int a,n,x,y,ans=0;
51     scanf("%d%d%d%d",&n,&m,&x,&y);
52     while(x!=-1&&y!=-1)
53     {
54         dp[x][y]=1;
55         scanf("%d%d",&x,&y);
56     }
57     for(int i=1;i<=n;i++)
58         dp[0][i]=1;
59     for(int i=n+1;i<=m;i++)
60         dp[i][m+1]=1;
61     while(DFS())
62     {    
63         a=find(0,99999999);
64         while(a)
65         {
66             ans+=a;
67             a=find(0,99999999);
68         }
69     }
70     printf("%d",ans);
71     return 0;
72 }
View Code

相关文章: