原题目有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
#include
#include
#include
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;
}
我在下载内容放输入和输出数据自己本机评测。