圖論:匈牙利算法


其實在寫這個的代碼的時候我是納悶的,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 }

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM