二分匹配總結
首先講一下什么是二分圖,在一個圖中,以邊為條件,能將兩個端點划分為兩個集合的圖叫做二分圖,如下圖:
左圖為二分圖,右圖為簡化后的二分圖。
接着就是二分圖的匹配問題,二分圖的匹配就是找一個邊的集合,每條邊的的頂點的度數為1。
如上圖所示,匹配到四條邊。
二分圖的完美匹配,就是所有的頂點都有匹配點,這樣的叫做完美匹配,上圖所示所有的點都有匹配點,所以可以成為完美匹配,並不是所有的圖都有完美匹配的。
講完了理論部分,那怎么樣實現二分圖的匹配問題吶,這里就引出了匈牙利算法,匈牙利算法的核心思想就是“能上就上,不能上創造條件也要上”
以下圖為例:
首先給1號同學找對象,找到了5號;
然后再給2號同學找對象,找到了5號,但是5號同學已經有對象了怎么辦吶,辦法了,只能讓5號先跟1號分手,重新給1號找對象,這時候一號的對象就換成了7號,而2號同學就和5號同學在一起了;
接下來就是給3號同學找對象了,找到了5號同學,但是5號同學已經有2號同學了,沒辦法了,先讓2號同學和五號同學分手,剛分手就發現,2號同學除了5號就找不到對象了,所以只能放棄,讓3號同學找下一個對象,這樣3號同學就找到了,6號同學。
最后就是給4號同學找對象,4號喜歡7號,唉…….這關系我都有點蒙了,多關注一下90后孤獨老人,年輕人關系這么復雜……沒辦法了讓7號先和1號分手吧,分手只有又發現問題了,1號又沒有對象了,所以還是不能分手,只能讓4號重新找對象了,這樣4號就找到了8號這樣,就完成了,這8個人的匹配問題……
通過代碼實現的時候就是利用dfs,給每個人找對象的時候先向上搜索看能不能創造條(fen)件(shou)來進行匹配,如果不能的話只能自己重新找對象了。
/***********************二分匹配模板**************************/ const int MAXN=1000; int uN,vN; //u,v數目 int g[MAXN][MAXN];//編號是0~n-1的 int linker[MAXN];//記錄匹配點i的匹配點是誰 bool used[MAXN]; bool dfs(int u)//回溯看能不能通過分手來進行匹配 { int v; for(v=0;v<vN;v++) if(g[u][v]&&!used[v]) //如果有這條邊,並且這條邊沒有用過 { used[v]=true; if(linker[v]==-1||dfs(linker[v]))//如果這個點沒有匹配過,並且能找到匹配點,那么就可以以這個邊作為匹配點 { linker[v]=u; return true; } } return false; } int hungary()//返回最大匹配數 { int res=0; int u; memset(linker,-1,sizeof(linker)); for(u=0;u<uN;u++) { memset(used,0,sizeof(used)); if(dfs(u))//如果這個點有匹配點 res++; } return res; } /***********************二分匹配模板**************************/