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

题目背景

第二次世界大战时期..

题目描述

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

输出格式:

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

思路

居然不输出No Solution!都可以AC……
这是一个网络流的躶题。
关键是建图
哪是源点,哪是汇点?
建一个!!!
源点连接外籍,汇点连接英籍。
最大流即为答案

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 20007
using namespace std;
struct E
{
    int to,c,next;
}e[maxn];
int cur[maxn],dis[maxn],list[maxn],cnt=1,n,m;
void add(int u,int v,int x)
{
    e[++cnt].to=v; e[cnt].c=x; e[cnt].next=list[u]; list[u]=cnt;
    e[++cnt].to=u; e[cnt].c=0; e[cnt].next=list[v]; list[v]=cnt;
}
bool bfs()
{
    memset(dis,0,sizeof(dis));
    queue<int> q;
    dis[0]=1; q.push(0);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=list[u]; i; i=e[i].next)
        {
            if(e[i].c&&!dis[e[i].to])
            {
                dis[e[i].to]=dis[u]+1;
                if(e[i].to==n+1) return 1;
                q.push(e[i].to);
            }
        }
    }
    return 0;
}
int dfs(int x,int maxf)
{
    if(x==n+1||!maxf) return maxf;
    int ret=0;
    for(int &i=cur[x]; i; i=e[i].next)
        if(e[i].c&&dis[e[i].to]==dis[x]+1)
        {
            int f=dfs(e[i].to,min(maxf-ret,e[i].c));
            e[i].c-=f;
            e[i^1].c+=f;
            ret+=f;
            if(maxf==ret) break;
        }
    return ret;
}
void dinic()
{
    int ass=0;
    while(bfs())
    {
        for(int i=0; i<=n+1; i++) cur[i]=list[i];
        ass+=dfs(0,0x3f3f3f3f);
    }
    printf("%d",ass);
    return;
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1; i<=m; i++) add(0,i,1);
    for(int i=m+1; i<=n; i++) add(i,n+1,1);
    while(1)
    {
        int x,y;
        scanf("%d%d",&x,&y); if(x==-1&&y==-1) break; add(x,y,1);
    }
//  printf("%d",dinic());
    dinic();
}





猜你喜欢

转载自blog.csdn.net/eric1561759334/article/details/80010954