匈牙利算法

重新写了一份,更新了一下注释

二分图匹配的具体知识可以参见维基百科

以下注释之适用于对于该程序的理解

/*
 *The HungarianAlgorithm
 *使用邻接表和DFS
 *时间复杂度O(mn)
 *空间复杂度O(m+n)
 *by volz.kz.g
 */
#include <cstring>
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("HA.in");
ofstream fout("HA.out");

const int MAXN = 1000;
struct node{
  int v;
  node *next;
};
node *g[MAXN];//定义邻接表
int n,m,p;//二分图左侧有N个顶点,右侧有M个顶点,两边共有P条边
bool use[MAXN];//该数组用来判断该二分图右侧节点在该次更新中是否被访问过
int last[MAXN];//该数组用来判断该二分图右侧节点是否被匹配过,并记录匹配到它的二分图左侧节点是什么
int ans;

/*
 *将边插入邻接表中
 */
inline void insert(int a,int b){
  node *x = new node;
  x->v=b;x->next=g[a];g[a]=x;
}

/*
 *寻找增广路径
 *判断从二分图左侧出发,
 *能否走到一个尚未被匹配的
 *二分图左侧的顶点
 */
bool augment(int x){
  node *t = g[t];
  while (t!=0){
    if (!use[t->v]){
      use[t->v]=true;
      if (last[t->v]==0 ||
	  augment(last[t->v])){//如果该右侧节点未被匹配或者匹配到它的左侧节点能够找到新的右侧节点来匹配
	last[t->v]=n;
	return true;
      }
    }
    t=t->next;
  }
  return false;
}

/*
 *初始化
 */
inline void init(){
  int a,b;
  fin >> n >> m >> p;
  for (int i=1;i<=p;i++){
    fin >> a >> b;
    insert(a,b);
  }
}

/*
 *寻找增广路径来更新最大匹配数量
 *对于二分图左侧的每一个顶点寻找增广路径
 */
inline void solve(){
  for (int i=1;i<=n;i++){
    memset(use,false,sizeof(use));
    if (augment(i)) ans++;
  }
}

inline void print(){
  fout << ans << endl;
}

int main(){
  init();
  solve();
  print();
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章