首页 > 代码库 > [COGS 0014][网络流24题] 搭配飞行员

[COGS 0014][网络流24题] 搭配飞行员

先贴题面

14. [网络流24题] 搭配飞行员

★★☆   输入文件:flyer.in   输出文件:flyer.out简单对比
时间限制:1 s   内存限制:128 MB

【问题描述】
    飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员。由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多。
技术分享
如图,假设有10个驾驶员,如图中的V1,V2,…,V10就代表达10个驾驶员,其中V1,V2,V3,V4,V5是正驾驶员,V6,V7,V8,V9,V10是副驾驶员。如果一个正驾驶员和一个副驾驶员可以同机飞行,就在代表他们两个之间连一条线,两个人不能同机飞行,就不连。例如V1和V7可以同机飞行,而V1和V8就不行。请搭配飞行员,使出航的飞机最多。注意:因为驾驶工作分工严格,两个正驾驶员或两个副驾驶员都不能同机飞行.
【输入格式】
输入文件有若干行
第一行,两个整数n与n1,表示共有n个飞行员(2<=n<=100),其中有n1名飞行员是正驾驶员.
下面有若干行,每行有2个数字a,b。表示正驾驶员a和副驾驶员b可以同机飞行。
注:正驾驶员的编号在前,即正驾驶员的编号小于副驾驶员的编号.
【输出格式】
输出文件有一行
第一行,1个整数,表示最大起飞的飞机数。
【输入输出样例】
输入文件名: flyer.in
10 5 
1 7 
2 6 
2 10 
3 7 
4 8 
5 9 
输出文件名:flyer.out
4
讲真确实是水题w简单的二分图最大匹配,可以转化为网络流来做.
首先建立超级源点$s$和$t$(编号$0$和$v+1$),从超级源点向所有正飞行员连一条容量为1的边,然后对于所有可能的匹配连一条从正飞行员到副飞行员的边,最后将所有副飞行员连接到超级汇点再跑一遍最大流就得了...
过于蒟蒻的我居然脑抽一开始觉得超级源点和超级汇点要连容量为INF的边...
好了代码时间
GitHub
技术分享
  1 #include <queue>  2 #include <cstdio>  3 #include <cstring>  4 #include <cstdlib>  5 #include <iostream>  6 #include <algorithm>  7   8 const int MAXE=10010;  9 const int MAXV=110; 10 const int INF=0x7FFFFFFF; 11  12 struct Edge{ 13     int from; 14     int to; 15     int flow; 16     Edge* rev; 17     Edge* next; 18 }; 19 Edge E[MAXE]; 20 Edge* head[MAXV]; 21 Edge* top=E; 22  23 int v,n; 24 int depth[MAXV]; 25  26 bool BFS(int,int); 27 int Dinic(int,int); 28 int DFS(int,int,int); 29 void Insert(int,int,int); 30  31 int main(){ 32     freopen("flyer.in","r",stdin); 33     freopen("flyer.out","w",stdout); 34     int a,b; 35     scanf("%d%d",&v,&n); 36     while(scanf("%d%d",&a,&b)==2){ 37         Insert(a,b,1); 38     } 39     for(int i=1;i<=n;i++){ 40         Insert(0,i,1); 41     } 42     for(int i=n+1;i<=v;i++){ 43         Insert(i,v+1,1); 44     } 45     printf("%d\n",Dinic(0,v+1)); 46     return 0; 47 } 48  49 int Dinic(int s,int t){ 50     int ans=0; 51     while(BFS(s,t)){ 52         ans+=DFS(s,INF,t); 53     } 54     return ans; 55 } 56  57 inline void Insert(int a,int b,int f){ 58     top->from=a; 59     top->to=b; 60     top->flow=f; 61     top->rev=top+1; 62     top->next=head[a]; 63     head[a]=top; 64     top++; 65     top->from=b; 66     top->to=a; 67     top->flow=0; 68     top->rev=top-1; 69     top->next=head[b]; 70     head[b]=top; 71     top++; 72 } 73  74 bool BFS(int s,int t){ 75     std::queue<int> q; 76     memset(depth,0,sizeof(depth)); 77     depth[s]=1; 78     q.push(s); 79     while(!q.empty()){ 80         int top=q.front(); 81         q.pop(); 82         for(Edge* i=head[top];i!=NULL;i=i->next){ 83             if(depth[i->to]==0&&i->flow!=0){ 84                 q.push(i->to); 85                 depth[i->to]=depth[top]+1; 86                 if(i->to==t) 87                     return true; 88             } 89         } 90     } 91     return false; 92 } 93  94 int DFS(int root,int flow,int t){ 95     if(root==t||flow==0) 96         return flow; 97     int tmp=flow; 98     int k; 99     for(Edge* i=head[root];i!=NULL;i=i->next){100         if(i->flow!=0&&tmp!=0&&depth[i->to]==depth[root]+1){101             k=DFS(i->to,std::min(tmp,i->flow),t);102             if(k==0){103                 depth[i->to]=0;104                 continue;105             }106             i->flow-=k;107             i->rev->flow+=k;108             tmp-=k;109             if(tmp==0)110                 break;111         }112     }113     return flow-tmp;114 }
Backup

以及图包w 

技术分享

[COGS 0014][网络流24题] 搭配飞行员