飞行员配对方案

文章目录


##题目大意:
只要外籍飞行员与英籍飞行员匹配就可以驾驶一架飞机,共有n个飞行员,其中有m个外籍的,问最多有多少对匹配的飞行员(一个外籍一个英籍)

##解题思路:
方法:网络流——最大流
匈牙利算法
这里用网络流——最大流
首先建一个源点和一个汇点,源点与外籍飞行员间建立一条有向边(外籍飞行员方向),汇点与英籍飞行员建立一条有向边(英籍飞行员方向)。
所有边的容量为1,也就是说流量最多为1。
然后求最大流,这个最大流就是最大匹配。

##源程序:

#include<cstdio>
#include<iostream> 
using namespace std;
int sum,b[102],f[102][102];
int a[102][102],u[102],v[102],ans,n,m,x,y;
bool find(int k)//找增广路
{
    if (k==m+1) return 1;
    //如果已经找到就退出(废话)
    for (int i=0;i<=m+1;i++)
      if (b[i]==-1&&((f[k][i]==0&&a[k][i])||f[i][k])) 
      //b[i]==-1说明没人与他匹配
      //f[k][i]==0也就是说可以与他匹配
      //a[k][i]是匹配前提,要能配对才可以"合作"
      //f[i][k]是逆向边,如果是逆向边而且已经反向"流"了
      //就可以合作
      {
         b[i]=k;
         //记录前驱
         if (find(i)) return 1;
         //递归判断是否是增广路
      }
    return 0;
}
void update()//更新
{
    int l=m+1;//从后往前去边
    while (l)
    {
        if (a[b[l]][l]) f[b[l]][l]++;
        //流量+1
        if (a[l][b[l]]) f[l][b[l]]--;
        //正向流和逆向流抵消
        l=b[l];
        //继续往前搜
    }
    ans++;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
     a[0][i]=1;
    //源点连外籍飞行员
    for (int j=n+1;j<=m+1;j++)
     a[j][m+1]=1;
    //英籍飞行员连汇点
    while (x!=-1&&y!=-1)
     scanf("%d%d",&x,&y),a[x][y]=1;
    //读入,建图(边)
    for (int i=0;i<=m+1;i++) b[i]=-1;
    b[0]=0;
    //初始化
    while (find(0))//找增广路
    {
        update();
        for (int i=1;i<=m+1;i++) b[i]=-1;
    }
    if (!ans) 
    {
        puts("No Solution!");
        return 0;
     }//如果没有(其实不打也AC,只是打了严谨一些)就输出No Solution!
    printf("%d\n",ans);
    //输出匹配总数
    for (int i=1;i<=n;i++)
    {
        for (int j=n+1;j<=m;j++)
            if (f[i][j]) {printf("%d %d\n",i,j);break;}
        //枚举找每一对匹配的飞行员
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值