1. 程式人生 > >使用匈牙利算法來解決二分圖的最大匹配問題

使用匈牙利算法來解決二分圖的最大匹配問題

%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 }

老實說,這個算法,真的很神奇。。

使用匈牙利算法來解決二分圖的最大匹配問題