题目背景

第二次世界大战时期..

题目描述

英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的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

Solution:

本题有两种方法。

方法一:明眼看,这道题一道裸的二分图最大匹配的题目,只需要判断并输出前趋数组pre和对应的i就OK了。

代码:

 #include<bits/stdc++.h>
using namespace std;
const int N=;
inline int gi()
{
char x=getchar();int a=,f=;
while(x<''||x>''){if(x=='-')f=-;x=getchar();}
while(x>=''&&x<=''){a=a*+x-'';x=getchar();}
return a*f;
}
int n,m,s,u,v;
struct edge
{
int v,ne;
}e[N*N<<];
int h[N],cnt;
inline void ins(int u,int v){
e[++cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
}
int le[N];
bool vis[N];
bool find(int u){
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(!vis[v]){
vis[v]=;
if(!le[v]||find(le[v])){
le[v]=u;
return ;
}
}
}
return ;
}
int ans;
int main(){
n=gi();m=gi();
while(){u=gi();v=gi();if(v==-)break;ins(u,v);}
for(int i=;i<=m;i++){
memset(vis,,sizeof(vis));
if(find(i)) ans++;
}
if(ans==)printf("No Solution!");
else {
printf("%d\n",ans);
for(int i=n+;i<=m;i++)
if(le[i])printf("%d %d\n",le[i],i);
}
return ;
}

方法二:学了网络流后,这道题也能用最大流做了。我们只需建立两个虚点S和T,S连向其中一个点集建n条边,T连向另一个点集建m条边,上述的边设置容量为1,然后照常对两个点集进行建边就行了(边设置容量为1),最后跑最大流就行了,当然也得记录并输出前趋。

代码(1):(非手打,搬运自巨佬YZK的ISAP)

 #include<bits/stdc++.h>
#define sins(x,y,z) ins(x,y,z),ins(y,x,0)
#define INF (0x7fffffff)
#define DEBUG printf("Passing %d in [%s]...\n",__LINE__,__FUNCTION__)
#define _rg register
using namespace std; template <typename T> void gn(T &x){
x=;
T pl=;
char ch=getchar();
while(ch<'' || ch>'') pl=(ch=='-'?-:), ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'', ch=getchar();
x*=pl;
} const int N=,M=2e5+;
int h[N],to[M],nexp[M],W[M],p=;
inline void ins(int a,int b,int w){
nexp[p]=h[a], h[a]=p, to[p]=b, W[p]=w, p++;
} int m,n;
int fl[N],rem[N];
int ISAP(int x,int op){
if(x==n+) return op;
int flow=,d,minfl=-;
// DEBUG;
for(_rg int u=h[x];u;u=nexp[u])
if(W[u]){
if(fl[to[u]]+==fl[x]) {
d=ISAP(to[u], op-flow<W[u]?op-flow:W[u]);
flow+=d, W[u]-=d, W[u^]+=d;
if(flow==op || fl[n+]==-) return flow;
}
if((minfl==- || minfl>fl[to[u]]+) && fl[to[u]]!=-) minfl=fl[to[u]]+;
}
// DEBUG;
if(!flow){
if(!(--rem[fl[x]])) fl[n+]=-;
fl[x]=minfl;
if(fl[x]!=-) rem[fl[x]]++;
}
return flow;
} int main(){
// ios::sync_with_stdio(false);
gn(m),gn(n);
int u,v;
while(gn(u),gn(v),u!=-) sins(u,v,);
for(int i=;i<=m;i++) sins(n+,i,);
for(int i=m+;i<=n;i++) sins(i,n+,); queue<int> qu;
qu.push(n+);
fl[n+]=, rem[]++;
while(!qu.empty()){
int na=qu.front();
qu.pop();
for(int u=h[na];u;u=nexp[u])
if(!W[u] && !fl[to[u]]){
fl[to[u]]=fl[na]+;
rem[fl[na]+]++;
qu.push(to[u]);
}
}
// DEBUG;
int ans=;
if(!fl[n+]) cout<<"No Solution!"<<endl;
while(fl[n+]!=-) ans+=ISAP(n+,INF);
cout<<ans<<endl;
for(int i=;i<=m;i++){
for(int u=h[i];u;u=nexp[u])
if(to[u]!=n+ && !W[u]) {cout<<i<<' '<<to[u]<<endl; break;}
}
return ;
}

代码2:(纯手打Dinic)

 #include<bits/stdc++.h>
#define il inline
using namespace std;
const int N=,inf=;
int m,n,dis[N],h[N],cnt=,ans,s,t;
struct edge{
int to,net,cap;
}e[];
il void add(int u,int v,int w)
{
e[++cnt].to=v,e[cnt].net=h[u],h[u]=cnt,e[cnt].cap=w;
e[++cnt].to=u,e[cnt].net=h[v],h[v]=cnt,e[cnt].cap=;
}
queue<int>q;
il bool bfs()
{
memset(dis,-,sizeof(dis));
dis[s]=;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=h[u];i;i=e[i].net)
{
int v=e[i].to;
if(dis[v]==-&&e[i].cap>){dis[v]=dis[u]+;q.push(v);}
}
}
return dis[t]!=-;
}
il int dfs(int u,int op)
{
if(u==t)return op;
int flow=,tmp=;
for(int i=h[u];i;i=e[i].net)
{
int v=e[i].to;
if(dis[v]==dis[u]+&&e[i].cap>){
tmp=dfs(v,min(op,e[i].cap));
if(!tmp)continue;
op-=tmp;flow+=tmp;
e[i].cap-=tmp;e[i^].cap+=tmp;
if(!op)break;
}
}
if(!flow)dis[u]=-;
return flow;
}
int main()
{
scanf("%d%d",&m,&n);
s=,t=n+;
int u,v,w;
while(){
scanf("%d%d",&u,&v);
if(u==-&&v==-)break;
add(u,v,);
}
for(int i=;i<=m;i++)add(s,i,);
for(int i=m+;i<=n;i++)add(i,n+,);
while(bfs())ans+=dfs(s,inf);
if(!ans)printf("No Solution!");
else {
printf("%d\n",ans);
for(int i=;i<=m;i++)
for(int j=h[i];j;j=e[j].net)
if(!e[j].cap&&e[j].to!=)printf("%d %d\n",i,e[j].to);
}
return ;
}

P2756 飞行员配对方案问题(网络流24题之一)的更多相关文章

  1. P2756 飞行员配对方案问题 网络流

    P2756 飞行员配对方案问题 #include <bits/stdc++.h> using namespace std; , inf = 0x3f3f3f; struct Edge { ...

  2. 洛谷 [P2756] 飞行员配对方案问题 网络流实现

    网络流实现二分图匹配 对于x集合的每一个点连一条从源点出发的容量为一的边,对于y集合的每一个点连一条到汇点的容量为一的边,跑最大流 #include <iostream> #include ...

  3. 洛谷P2756 飞行员配对方案问题 网络流_二分图

    Code: #include<cstdio> #include<queue> #include<vector> #include<cstring> #i ...

  4. 洛谷 P2756 飞行员配对方案问题 (二分图/网络流,最佳匹配方案)

    P2756 飞行员配对方案问题 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其 ...

  5. 洛谷P2756飞行员配对方案问题 P2055假期的宿舍【二分图匹配】题解+代码

    洛谷 P2756飞行员配对方案问题 P2055假期的宿舍[二分图匹配] 飞行员配对方案问题 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架 ...

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

    P2756 飞行员配对方案问题 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其 ...

  7. 洛谷 P2756 飞行员配对方案问题 (二分图匹配)

    题目链接:P2756 飞行员配对方案问题 题意 给定 \(m\) 个外籍飞行员和 \(n - m\) 个英国飞行员,每一架飞机需要一名英国飞行员和一名外籍飞行员,求最多能派出几架飞机. 思路 最大流 ...

  8. luogu P2756 飞行员配对方案问题

    题目链接:P2756 飞行员配对方案问题 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另 ...

  9. 洛谷P2756 飞行员配对方案问题(二分图匹配)

    P2756 飞行员配对方案问题 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其 ...

随机推荐

  1. 【BZOJ3489】A simple rmq problem

    [BZOJ3489]A simple rmq problem 题面 bzoj 题解 这个题不强制在线的话随便做啊... 考虑强制在线时怎么搞 预处理出一个位置上一个出现的相同数的位置\(pre\)与下 ...

  2. (三)SpringBoot2.0基础篇- 持久层,jdbcTemplate和JpaRespository

    一.介绍 SpringBoot框架为使用SQL数据库提供了广泛的支持,从使用JdbcTemplate的直接JDBC访问到完整的“对象关系映射”技术(如Hibernate).Spring-data-jp ...

  3. HTML基本代码教学,第三天

    HTML 今天由于个人情况,身体不适,但是为了大家的学习进度,咱们以纯文字得形式来简单了解下今天的学习内容 今儿咱们来了解下表单 <form id=" "  name=&qu ...

  4. (python)剑指Offer 面试题51:数组中重复的数字

    问题描述 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1, ...

  5. 换Mac了,迈入了终端的大门

    多终端其实本质和多线程一样,所有终端其实都共享着同一个内存只不过不同终端对共享内存不同部分的权限不同罢了所以对终端的数量必须要有限制 我这里开启了四个线程,很明显四个线程都在跑同一个内存而且四个线程都 ...

  6. mysql group by 取第一条

    select * from table where id in (select max(id) from table group by sku) 说明:id是自增序列,sku是表中的一个字段

  7. Linux下的计算器(bc、expr、dc、echo、awk)知多少?

    linux 其他知识目录 原文链接:http://blog.chinaunix.net/uid-24673811-id-1760837.html linux下的三个命令可以用来作计算,下面一一讲解用法 ...

  8. eclipse启动一闪而退

    eclipse启动一闪而退 打开eclipse,启动画面一闪而过退出. 解决方法: 以下每一步结束都重启eclipse一下,看能不能正常启动. 1. 在C:/WINDOWS/system32 系统文件 ...

  9. mysql数据库查询

    查询数据指从数据库中获取所需要的数据.查询数据是数据库操作中最常用,也是最重要的操作.用户可以根据自己对数据的需求,使用不同的查询方式.通过不同的查询方式,可以获得不同的数据.MySQL中是使用SEL ...

  10. __autoload 与spl_autoload_register()

    PHP __autoload函数(自动载入类文件)的使用方法 作者: 字体:[增加 减小] 类型:转载 时间:2012-02-04   在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都 ...