洛谷 P3386 【模板】二分图最大匹配

匈牙利算法博大精深,这里只记录步骤。

当然,不知道这些基础图论的童鞋请看这里(虽然也是草草概括一下谔谔谔)

主要步骤

\(main\)

主函数里面一个枚举现在正在匹配的左点

对于每个准备匹配的左点,进行一边\(dfs\)

\(dfs\)有两个参数,现在正在匹配的点 和 现在正在枚举到的点(后面说这个有什么意义)

\(dfs\)

每次\(dfs\)时扫描时,扫描当前左点u的所有连接的右点v。这时候,会出现两种情况:

  • 这个右点v还没有被选过,就直接将左点和右点匹配即可,\(match[v]=u\)
  • 这个右点v已经被\(match[v]\)选过了,那么向\(match[v]\)询问能不能换一个对应的点来选。注意这样搜索时,对右点要打上访问标记\(vis\)来记录这个右点是否被换过左点,防止死循环

那么好了,为什么要\(dfs\)两个参数呢?

其实,第二个参数是用来打标记的。试想,每次枚举(不是\(dfs\))到一个点的时候,所有右点的\(vis\)就要清空一边。那么时间复杂度就会退化成\(O(n^2)\)的!而使用第二个参数来打标记的话,每次的标记编号更新,就意味着所有之前打的标记全部失效了。用\(O(1)\)的时间就完成了\(O(n)\)的任务!

例题

来一道模板题吧!

不过因为这道题的数据较小,看不出优化标记的差别呢……

image-20201104092544777

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define re register
#define debug printf("Now is %d\n",__LINE__);
using namespace std;

template<class T>inline void read(T&x)
{
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
}
inline int read()
{
	int x=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x;
}
int G[55];
template<class T>inline void write(T x)
{
    int g=0;
    if(x<0) x=-x,putchar('-');
    do{G[++g]=x%10;x/=10;}while(x);
    for(re int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n,m,e,ans;
vector<int>L[5001];
int match[5001],vis[5001];
bool dfs(int x,int tag)
{
	if(vis[x]==tag) return false;
	vis[x]=tag;
	for(int i=0;i<L[x].size();i++)
	{
		if(match[L[x][i]]==0||dfs(match[L[x][i]],tag))
		{
			match[L[x][i]]=x;
			return true;
		}
	}
	return false;
}
int main()
{
	n=read();
	m=read();
	e=read();
	for(int i=1,t;i<=e;i++) t=read(),L[t].push_back(read());
	for(int i=1;i<=n;i++)
	{
		if(dfs(i,i)) ans++;
	}
	cout<<ans;
	return 0;
}
posted @ 2020-11-04 09:33  Vanilla_chan  阅读(168)  评论(0)    收藏  举报