二分圖匹配之匈牙利算法
阿新 • • 發佈:2018-10-02
%d 成功 || 集合 truct ons 原因 strong 二分圖匹配
二分圖匹配的問題都可以用網絡流來做,但是二分圖匹配的一些思想還是得了解一下。
匈牙利算法:
我們將左邊集合記為S,右邊集合記為T,
加邊的時候只需要加S---->T的邊,∞後面會提到原因。
我們枚舉點進行增廣,增廣的時候只訪問當次增廣沒有訪問到的點。
什麽情況下才算是成功的增廣?
u---->v的v點沒有匹配過,或者當前匹配v的點還能找到一個點去匹配,
這樣u就與v匹配。並且每次枚舉點,就要清空vis數組,因為我們不希望
在一次增廣中重復訪問訪問過的結點。
∞reason:每一次成功的增廣都只需要從S集合中在T集合中找匹配,
繼續用記錄v有沒有被匹配,每次都會從u去找匹配。
代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<map> #define ll long long int using namespace std; const int N=1e6+5; int n,m,ee,num=1,ans; int cx[N],cy[N],vis[N],head[N]; struct E{ int nxt,to; }e[N]; void add(intu,int v){ e[++num].to=v; e[num].nxt=head[u]; head[u]=num; } int dfs(int u){ for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(!vis[v]){ vis[v]=1; if((!cy[v])||(dfs(cy[v]))){ cy[v]=u; return 1; } } }return 0; } void max_match(){ for(int u=1;u<=n;u++){ memset(vis,0,sizeof(vis)); ans+=dfs(u); } } int main(){ scanf("%d%d%d",&n,&m,&ee); for(int i=1;i<=ee;i++){ int u,v; scanf("%d%d",&u,&v); if(u<=n&&v<=m) add(u,v); } max_match(); printf("%d",ans); return 0; }
二分圖匹配之匈牙利算法