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

原题目有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;
}

我在下载内容放输入和输出数据自己本机评测。

你可能感兴趣的:(最大流)