您的位置:首页 > 理论基础 > 计算机网络

【网络流24题】飞行员配对方案问题

2016-04-20 16:18 357 查看
原题目有special judge所以我将题目去掉special judge之后如下:

问题描述:

第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出

的每一架飞机都需要配备在航行技能和语言上能互相配合的 2 名飞行员,其中 1 名是英国飞

行员,另 1 名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英

国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的

外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空

军一次能派出最多的飞机。

编程任务:

对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,

使皇家空军一次能派出最多的飞机。

数据输入:

由文件 air.in 提供输入数据。文件第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行

员总数(n<100);m 是外籍飞行员数。外籍飞行员编号为 1~m;英国飞行员编号为 m+1~n。

接下来每行有 2 个正整数 i 和 j,表示外籍飞行员 i 可以和英国飞行员 j 配合。文件最后以 2

个-1 结束。

结果输出:

程序运行结束时,将最佳飞行员配对方案输出到文件air.out 中。第 1 行是最佳飞行

员配对方案一次能派出的最多的飞机数 M。 如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。

输入文件示例

air.in

5 10

1 7

1 8

2 6

2 9

2 10

3 7

3 8

4 7

4 8

5 10

-1 -1

输出文件示例

air.out

4

这是一个二分图问题但是我们可以将该问题转化为最大流问题。具体如下建模。

引入一个超级源T和一个超级汇S,从T向外国飞行员设置容量为1的边,从英国飞行员向S设置容量为1的边,最后将所有可以搭配的外国飞行员和英国飞行员连起容量为1的边。

下面是代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;

const int MAXN = 1050,T = 0,S = 104,INF = 10000000;

int N,M,e = 2,ans,d[MAXN],head[MAXN];

struct node{
int v,c,f,next;
}edge[20000000];

queue<int>q;

inline int read(){
int x = 0, f = 1;char ch = getchar();
while(ch < '0' || '9' < ch) {if(ch == '-') f = -1;ch = getchar();}
while('0'<= ch && ch <='9') {x = x *10 + ch - '0';ch = getchar();}
return x * f;
}

inline void addedge(int u,int v,int f,int c){
edge[e].next = head[u];edge[e].v = v;edge[e].f = 0;edge[e].c = c;head[u] = e++;
}

inline void build(int u,int v,int f,int c)
{
addedge(u,v,0,c);addedge(v,u,0,0);
}

inline void init()
{
M = read();N = read();

for(int i = 1;i <= M;i++)build(T,i,0,1);

int a,b;

while(1){
a = read();b = read();build(a,b,0,1);
if(a == -1 && b == -1) break;
}

for(int i = 1;i <= N;i++) build(i+M,S,0,1);

}

inline int Dinic(int u,int a){
if(u == S || a == 0) return a;
int f,flow = 0;
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].v;
if(d[v] == (d[u] + 1) && (f = Dinic(v,min(a,edge[i].c - edge[i].f))) > 0)
edge[i].f += f;
edge[i^1].f -= f;
flow += f;
a -= f;
if(a == 0) break;
}
return flow;
}

inline bool bfs(int u)
{
memset(d,0,sizeof(d));
q.push(u);d[u] = 1;
int x;
while(!q.empty()){
x = q.front();q.pop();
for(int i = head[x];i;i = edge[i].next){
int v = edge[i].v;
if(!d[v] && edge[i].c > edge[i].f){
d[v] = d[x] + 1;
q.push(v);
}
}
}
if(d[S]) return true;
return false;
}

int main()
{
freopen("air.in","r",stdin);
freopen("air.out","w",stdout);
init();ans = 0;
while(bfs(0))
{
ans += Dinic(0,INF);
}
if(ans) printf("%d",ans);
else printf("No Solution!")
return 0;
}


我在下载内容放输入和输出数据自己本机评测。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: