• 二分图最大匹配:Ho-Kashyap算法


    俗称HK算法。和匈牙利算法一个功能,但是复杂度更优。匈牙利算法复杂度O(VE),HK算法复杂度O(sqrt(V)*E)。

    但是很容易写崩,别问我怎么知道的。

      1 #include<bits/stdc++.h>
      2  using namespace std;
      3  const int MAXN=500;// 最大点数
      4  const int INF=1<<28;// 距离初始值
      5  int bmap[MAXN][MAXN];//二分图
      6  int cx[MAXN];//cx[i]表示左集合i顶点所匹配的右集合的顶点序号
      7  int cy[MAXN]; //cy[i]表示右集合i顶点所匹配的左集合的顶点序号
      8  int nx,ny;
      9  int dx[MAXN];
     10  int dy[MAXN];
     11 /*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号*/
     12  int dis;
     13  bool bmask[MAXN];
     14  //寻找 增广路径集
     15  bool searchpath()
     16  {
     17     queue<int>Q;
     18     dis=INF;
     19     memset(dx,-1,sizeof(dx));//第几层
     20     memset(dy,-1,sizeof(dy));
     21     for(int i=1;i<=nx;i++)
     22     {
     23        //cx[i]表示左集合i顶点所匹配的右集合的顶点序号
     24        if(cx[i]==-1)
     25        {
     26           //将未遍历的节点 入队 并初始化次节点距离为0
     27           Q.push(i);
     28           dx[i]=0;//第0层
     29        }
     30     }
     31     //广度搜索增广路径
     32     while(!Q.empty())
     33     {
     34        int u=Q.front();
     35        Q.pop();
     36        if(dx[u]>dis) break;
     37        //取右侧节点
     38        for(int v=1;v<=ny;v++)
     39        {
     40           //右侧节点的增广路径的距离
     41           if(bmap[u][v]&&dy[v]==-1)
     42           {
     43              dy[v]=dx[u]+1; //v对应的距离 为u对应距离加1
     44              if(cy[v]==-1) dis=dy[v];     //如果该点未被匹配,那么增广路形成
     45              else                         //如果该点匹配了,那么接着往下搜
     46              {
     47                 dx[cy[v]]=dy[v]+1;
     48                 Q.push(cy[v]);
     49              }
     50           }
     51        }
     52     }
     53     return dis!=INF;
     54  }
     55  //寻找路径 深度搜索
     56  int findpath(int u)
     57  {
     58     for(int v=1;v<=ny;v++)
     59     {
     60        //如果该点没有被遍历过 并且距离为上一节点+1
     61        if(!bmask[v]&&bmap[u][v]&&dy[v]==dx[u]+1)
     62        {
     63           //对该点染色
     64           bmask[v]=1;
     65           if(cy[v]!=-1&&dy[v]==dis)   //如果该点已经被匹配了并且为最后一个匹配点,那么这条路径不是增广路。即是说这条路的结点已经匹配
     66           {
     67              continue;
     68           }
     69           if(cy[v]==-1||findpath(cy[v]))  //如果该点未匹配或者后面的点能腾出位置,那么这就是增广路
     70           {
     71              cy[v]=u;cx[u]=v;
     72              return 1;
     73           }
     74        }
     75     }
     76     return 0;
     77  }
     78  //得到最大匹配的数目
     79  int MaxMatch()
     80  {
     81     int res=0;
     82     memset(cx,-1,sizeof(cx));
     83     memset(cy,-1,sizeof(cy));//cx[i]表示左集合i顶点所匹配的右集合的顶点序号
     84     while(searchpath())    //如果存在增广路 一直迭代到无增广路
     85     {
     86        memset(bmask,0,sizeof(bmask));//标记数组
     87        for(int i=1;i<=nx;i++)
     88        {
     89           if(cx[i]==-1)
     90           {
     91              res+=findpath(i);
     92           }
     93        }
     94     }
     95     return res;
     96  }
     97  int main()
     98  {
     99     int num;
    100     scanf("%d",&num);
    101     while(num--)
    102     {
    103        memset(bmap,0,sizeof(bmap));
    104        scanf("%d%d",&nx,&ny);
    105        for(int i=1;i<=nx;i++)
    106        {
    107           int snum;
    108           scanf("%d",&snum);
    109           int u;
    110           for(int j=1;j<=snum;j++)
    111           {
    112              scanf("%d",&u);
    113              bmap[i][u]=1;
    114             // bmap[u][i]=1;
    115           }
    116        }
    117       // cout<<MaxMatch()<<endl;
    118        if(MaxMatch()==nx)
    119        {
    120           printf("YES
    ");
    121        }
    122        else
    123        {
    124           printf("NO
    ");
    125        }
    126     }
    127     //system("pause");
    128     return 0;
    129  }
  • 相关阅读:
    编译用到boost相关的东西,问题的解决;以及和googletest库
    看开源代码利器—用Graphviz + CodeViz生成C/C++函数调用图(call graph)
    centos5 升级到centos6
    Go vs Erlang
    Graphviz
    Oracle相关安装经验总结
    学习erlang书籍
    sublime使用总结
    List集合五种遍历方式
    nginx常用命令
  • 原文地址:https://www.cnblogs.com/St-Lovaer/p/11945648.html
Copyright © 2020-2023  润新知