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

2021年09月15日 阅读数:4
这篇文章主要向大家介绍洛谷P3386 :【模板】二分图匹配,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

https://www.luogu.org/problemnew/show/P3386html

题目描述

给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数算法

输入输出格式

输入格式:网络

 

第一行,n,m,eide

第二至e+1行,每行两个正整数u,v,表示u,v有一条连边spa

 

输出格式:code

 

共一行,二分图最大匹配htm

 

输入输出样例

输入样例#1: 复制get

1 1 1
1 1

输出样例#1: 复制string

1

说明

n,m≤1000 , 1≤u≤n , 1≤v≤m,e≤n×mit

由于数据有坑,可能会遇到 v>m 或者 u>n 的状况。请把 v>m 或者 u>n的数据自觉过滤掉。

算法:二分图匹配

 

未用邻接表:

#include <stdio.h>
#include <string.h>
using namespace std;
#define N 1020
int e[N][N];
int book[N], l[N], n, m;
int dfs(int s)
{
	int i, len, j;
	
	for(i=1; i<=m; i++)
	{
		if(book[i]==0 && e[s][i])
		{
			book[i]=1;
			if(l[i]==0 || dfs(l[i]))
			{
				l[i]=s;
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	int i, j, u, v, ans, w;
	scanf("%d%d%d", &n, &m, &w);
	for(i=0; i<w; i++)
	{
		scanf("%d%d", &u, &v);
		if(u>n || v>m)
			continue;
		e[u][v]=1;
	}
	ans=0;
	for(i=1; i<=n; i++)
	{
		memset(book, 0, sizeof(book));
		if(dfs(i))
			ans++;
	}
	printf("%d\n", ans);
	return 0;
} 

 邻接表写法:

#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
#define N 1020
vector<int>e[N];
int book[N], l[N];
int dfs(int s)
{
	int i, len, j, x;
	len=e[s].size();
	for(i=0; i<len; i++)
	{
		x=e[s][i];
		if(book[x]==0)
		{
			book[x]=1;
			if(l[x]==0 || dfs(l[x]))
			{
				l[x]=s;
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	int n, m, i, j, u, v, ans, w;
	scanf("%d%d%d", &n, &m, &w);
	memset(l, 0, sizeof(l));
	for(i=0; i<w; i++)
	{
		scanf("%d%d", &u, &v);
		if(u>n || v>m)
			continue;
		e[u].push_back(v);
	}
	ans=0;
	for(i=1; i<=n; i++)
	{
		memset(book, 0, sizeof(book));
		if(dfs(i))
			ans++;
	}
	printf("%d\n", ans);
	return 0;
} 

网络最大流:

#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
#define N 2020
int book[N], l[N], n, m, inf=99999999;
struct edge{
	int to;
	int cap;
	int rev;
}; 
vector<edge>G[N];
void add (int from, int to)
{
	int cap=1;
	G[from].push_back((edge){to, cap, G[to].size()});
	G[to].push_back((edge){from, 0, G[from].size()-1});
}
int dfs(int v, int t, int f)
{
	int i;
	if(v==t)
		return f;
	book[v]=1;
	for(i=0; i<G[v].size(); i++)
	{
		edge &e=G[v][i];
		if(!book[e.to] && e.cap>0){
			int d=dfs(e.to, t, min(f, e.cap));
			if(d>0)
			{
				//G[v][i].cap-=d;
				e.cap-=d;
				G[e.to][e.rev].cap+=d;
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s, int t)
{
	int flow=0;
	while(1)
	//for(;;)
	{
		memset(book, 0, sizeof(book));
		int f=dfs(s, t, inf);
		if(f==0)
			return flow;
		flow+=f;
	}
}
int main()
{
	int i, u, v, s;
	scanf("%d%d%d", &n, &m, &s);
	for(i=1; i<=n; i++)
		add(0,i);
	for(i=n+1; i<=n+m; i++)
		add(i, m+n+1);
	while(s--)
	{
		scanf("%d%d", &u, &v);
		if(v>m || u>n)
			continue;
		add(u, v+n);
	}
	printf("%d\n", max_flow(0, n+m+1));
	return 0;
}