匈牙利算法

重新寫了一份,更新了一下注釋

二分圖匹配的具體知識可以參見維基百科

以下注釋之適用於對於該程序的理解

/*
 *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();
}


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