使用匈牙利算法來解決二分圖的最大匹配問題
阿新 • • 發佈:2018-08-07
%d clas 集合 真的 ems 表示 int 選擇 ring
其實在寫這個的代碼的時候我是納悶的,X集合和Y集合的點,能同時用1,或者2來表示嗎?
然後我努力說服自己:它已經是二分圖了
它就是存了一個 → 而已
好的我被自己說服了
二分圖匹配說的就是,每個人有若幹種選擇,但是每種選擇只能容納一個人,問你最多能配對多少
或者說成選邊的時候不能經過同一個點
最大匹配就是最多選擇多少條邊的問題
匈牙利算法就是,有機會就上,沒機會要創造機會也要上,盡可能地給當前騰地方,騰的過程是一個遞歸的過程
其實這個算法挺矯情的。。
bool find(int u) { for(int tmp=g[u];tmp;tmp=e[tmp].next) if(!y[e[tmp].t]) { y[e[tmp].t]=1; if(lk[e[tmp].t]==0||find(lk[e[tmp].t])) { lk[e[tmp].t]=u; return 1; } } return 0; }
建圖之後,對於每個X中的點,清空y數組之後find就好了
然後忘了說定義了,補上。。
int n,m,cnt,ans; int y[maxn],lk[maxn],g[maxn];
y記錄的是Y中的下標節點是否被訪問過
lk記錄的是與當前下標節點(Y中)相連的X中的節點
然後給出完整實現:
1 #include<cstdio> 2 #include<cstring> 3 const int maxn=205; 4 const int maxm=205; 5 int n,m,cnt,ans; 6 int y[maxn],lk[maxn],g[maxn]; 7 struct Edge{int t,next;}e[maxn*maxm]; 8 void addedge(int u,int v) 9 { 10 e[++cnt].t=v;e[cnt].next=g[u];11 g[u]=cnt; 12 } 13 bool find(int u) 14 { 15 for(int tmp=g[u];tmp;tmp=e[tmp].next) 16 if(!y[e[tmp].t]) 17 { 18 y[e[tmp].t]=1; 19 if(lk[e[tmp].t]==0||find(lk[e[tmp].t])) 20 { 21 lk[e[tmp].t]=u; 22 return 1; 23 } 24 } 25 return 0; 26 } 27 int main() 28 { 29 scanf("%d%d",&n,&m); 30 int tmp,tmp1; 31 for(int i=1;i<=n;i++) 32 { 33 scanf("%d",&tmp); 34 for(int j=1;j<=tmp;j++) 35 { 36 scanf("%d",&tmp1); 37 addedge(i,tmp1); 38 } 39 } 40 for(int i=1;i<=n;i++) 41 { 42 memset(y,0,sizeof(y)); 43 if(find(i)) ans++; 44 } 45 printf("%d",ans); 46 return 0; 47 }
老實說,這個算法,真的很神奇。。
使用匈牙利算法來解決二分圖的最大匹配問題