• 网络流24题-飞行员配对方案问题-二分图最大匹配


      这道题,是个人都看得出来,是求一个二分图的最大匹配。

      但是网络流24题嘛,我们考虑一下用网络流的方法做。

      一般二分图的题,转网络流做,都需要建立一个起点和汇点。然后求一个最大流,这个最大流就是二分图的最大匹配。

      我用的是Edmonds-Karp算法bfs版本

      代码

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n,m,s,t,tot,maxflow;
    const int inf = 1<<29,N=2010,M=20010;
    int head[N],ver[M],edge[M],Next[M],v[N],incf[N],pre[N];
      //邻接表最后一个点(表头),下一个节点,流量,邻接表,数组,增广路上各边最小剩余容量,路径记录
    void add(int x,int y,int z){
       ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;//正向边
       ver[++tot]=x,edge[tot]=0,Next[tot]=head[y],head[y]=tot;//反向边
    }
    bool bfs(){
      memset(v,0,sizeof(v));
      queue<int>q;
      q.push(s);
      v[s]=1;
      incf[s]=inf;//增广路上各边最小剩余容量
      while(q.size()){
        int x=q.front();
        q.pop();
        for (int i=head[x];i!=-1;i=Next[i])//开始广度遍历
           if (edge[i]){//流量不为0
              int y=ver[i];
              if(v[y])continue;//这条边在当前的BFS里面已经走过了
              incf[y]=min(incf[x],edge[i]);
              pre[y]=i;//记录前驱,方便把方案保存下来
              q.push(y),v[y]=1;
              if (y==t)return 1;//成功
           }
      }
      return 0;//失败
    }
    void update(){
      int x=t;
      while(x!=s){
         int i=pre[x];
         edge[i]-=incf[t];//更新流量
         edge[i^1]+=incf[t];//更新反向流量
         x=ver[i^1];
      }
      maxflow+=incf[t];
    }
    int main(){
      int tmp1,tmp2;
      while(~scanf("%d%d",&m,&n)){
        memset(head,-1,sizeof(head));
        s=0,t=n+1,tot=1,maxflow=0;
        while(1){
            scanf("%d%d",&tmp1,&tmp2);
            if (tmp1==-1 && tmp2==-1)
                break;
            add(tmp1,tmp2,0x3f3f3f3f);
        }
        for (int i=1;i<=m;i++){
            add(s,i,1);
        }
        for (int i=m+1;i<=n;i++){
            add(i,t,1);
        }
        while(bfs())
            update();
        printf("%d
    ",maxflow);
        for (int i=2;i<=tot;i+=2){
            if((ver[i^1]!=s && ver[i]!=t)&&(ver[i]!=s && ver[i^1]!=t))//不能是直接指向起点和汇点的点
            if (edge[i^1]!=0)
            printf("%d %d
    ",ver[i^1],ver[i]);
        }
      }
      return 0;
    }

     留坑匈牙利算法

    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    机器学习-数据可视化神器matplotlib学习之路(四)
    [AspNetCore]CookieAuthentication禁用自动跳转到登录页
    [AspNetCore3.1] 使用Serilog记录日志
    [排序算法二]选择排序
    [排序算法一]冒泡排序
    Ocelot 网关 和 consul 服务发现
    AspNetCore3.0 和 JWT
    在AspNetCore3.0中使用Autofac
    【ElasticSearch+NetCore 第二篇】Nest封装
    【ElasticSearch+NetCore 第一篇】在Windows上安装部署ElasticSearch和ElasticSearch-head
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/10434865.html
Copyright © 2020-2023  润新知