1. 程式人生 > >二分圖匹配之匈牙利算法

二分圖匹配之匈牙利算法

%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(int
u,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; }

二分圖匹配之匈牙利算法