洛谷P2756 飞行员配对方案问题

Posted lonlyn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P2756 飞行员配对方案问题相关的知识,希望对你有一定的参考价值。

题目:https://www.luogu.org/problemnew/show/2756

题目背景

第二次世界大战时期..

题目描述

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

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

输入输出格式

输入格式:

 

第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行员总数(n<100);m 是外籍飞行员数(m<=n)。外籍飞行员编号为 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 

解析

网络流24题之一orz。

二分图最大匹配。

 

S和外籍连容量为1的边。

英籍和T连容量为1的边。

外籍和英籍能一块的连容量为1的边。

跑最大流,得最大数量。

 

查找连接英籍与外籍飞行员的边。

如果满流,则输出两人编号。

 

技术分享图片
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<vector>
  8 #define inf 2<<29
  9 #define S 0
 10 #define T 300
 11 using namespace std;
 12 
 13 struct line{
 14     int from,to;
 15     int cap,flow;
 16 };
 17 vector<line> edge;
 18 vector<int> G[330];
 19 
 20 int m,n;
 21 int x,y;
 22 int ans,cnt;
 23 
 24 int vis[330];
 25 int cur[330];
 26 int dis[330];
 27 
 28 void addedge(int from,int to,int cap){
 29     edge.push_back((line){from,to,cap,0});
 30     edge.push_back((line){to,from,0,0});
 31     int m=edge.size();
 32     G[from].push_back(m-2);
 33     G[to].push_back(m-1);
 34 }
 35 
 36 bool bfs(){
 37     memset(vis,0,sizeof(vis));
 38     queue<int> q;
 39     q.push(S);
 40     dis[S]=0;
 41     vis[S]=1;
 42     while (!q.empty()){
 43         int now=q.front();
 44         q.pop();
 45         for (int i=0;i<G[now].size();++i){
 46             line e=edge[G[now][i]];
 47             if (!vis[e.to]&&e.cap>e.flow){
 48                 q.push(e.to);
 49                 vis[e.to]=1;
 50                 dis[e.to]=dis[now]+1;
 51             }
 52         }
 53     }
 54     return vis[T];
 55 }
 56 
 57 int dfs(int x,int a){
 58     if (x==T||a==0) return a;
 59     int f,flow=0;
 60     for (int& i=cur[x];i<G[x].size();++i){
 61         line& e=edge[G[x][i]];
 62         if ((dis[e.to]==dis[x]+1)&&(f=dfs(e.to,min(a,e.cap-e.flow)))){
 63             flow+=f;
 64             a-=f;
 65             e.flow+=f;
 66             edge[G[x][i]^1].flow-=f;
 67             if (!a) break;
 68         }
 69     }
 70     return flow;
 71 }
 72 
 73 void dinic(){
 74     while (bfs()){
 75         memset(cur,0,sizeof(cur));
 76         ans+=dfs(S,inf);
 77     }
 78 }
 79 
 80 int main(){
 81     scanf("%d%d",&m,&n);
 82     for (int i=1;i<=m;++i)
 83       addedge(S,i,1);
 84     for (int i=1;i<=n;++i)
 85       addedge(i+m,T,1);
 86     scanf("%d%d",&x,&y);
 87     while (x!=-1&&y!=-1){
 88         addedge(x,y+m,1);
 89         scanf("%d%d",&x,&y);
 90     }
 91     dinic();
 92     if (ans==0){
 93         printf("No Solution!");
 94         return 0;
 95     }
 96     printf("%d\n",ans);
 97     
 98     int maxsize=edge.size(); 
 99     
100     for (int i=0;i<maxsize;i+=2){
101         if (edge[i].flow==1&&
102             edge[i].from!=S&&edge[i].to!=T){
103                 printf("%d %d\n",edge[i].from,edge[i].to-m);
104                 ++cnt;
105                 if (cnt==ans) break;
106             }
107     }
108     return 0;
109 }
View Code

 

 

 

 

以上是关于洛谷P2756 飞行员配对方案问题的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2756 飞行员配对方案问题

洛谷 P2756 飞行员配对方案问题

洛谷P2756 飞行员配对方案问题

P2756 飞行员配对方案问题(二分图)

P2756 飞行员配对方案问题

P2756 飞行员配对方案问题