Luogu P3386 [template] Bipartite graph maximum matching (network maximum flow)

Topic link

Title description

Given a bipartite graph, the number of points on the left is n, the number of points on the right is m, and the number of sides is e, find the maximum matching number of sides.

The left points are numbered from 1 to n, and the right points are numbered from 1 to m.

Input format

The first line of input is three integers, representing n, m, and e.

In the next row e, each row contains two integers u, v, which means that there is an edge connecting the left point u and the right point v.

Output format

Output an integer on a line, representing the maximum number of matching edges of the bipartite graph.

Enter #1

1 1 1
1 1

Output #1

1

Input #2

4 2 7
3 1
1 2
3 2
1 1
4 2
4 1
1 1

Output #2

2

Ideas

The key to solving the maximum matching problem of bipartite graphs with network flow is the problem of mapping. How to determine S and T? We need to set up two super source points to connect with the corresponding parts to make the solution feasible.

Code

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int maxn=1e4+5;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
ll e,s,u,v,w,t,m,n,cnt,cur[maxn],dep[maxn],head[maxn];
struct node
{
    
    
	ll val;
	int v,next;
}a[maxn*maxn];
void add(int u,int v,ll val)
{
    
    
	a[cnt].v=v;
	a[cnt].val=val;
	a[cnt].next=head[u];
	head[u]=cnt++;
	//反向建边 
	a[cnt].v=u;
	a[cnt].val=0;
	a[cnt].next=head[v];
	head[v]=cnt++;
}
bool bfs(int s)//源点和汇点,该bfs函数用来确定深度(层次) 
{
    
    
	queue<int> que;
	memset(dep,0,sizeof dep);
	for(int i=1;i<=n;i++)
		cur[i]=head[i];
	int u=s;
	dep[u]=1;
	que.push(u);
	while(!que.empty())
	{
    
    
		int u=que.front();
		que.pop();
		for(int i=head[u];~i;i=a[i].next)
		{
    
    
			int v=a[i].v;
			ll val=a[i].val;
			if(!dep[v]&&val)
			{
    
    
				dep[v]=dep[u]+1;
				que.push(v);
			}
		}
		if(dep[t])
			return true;
	}
	return false;
}
ll dfs(int u,ll uv)
{
    
    
	
	if(u==t)
		return uv;
	ll used=0;
	for(int i=cur[u];~i;i=a[i].next)
	{
    
    
		cur[u]=i;
		int v=a[i].v;
		ll val=a[i].val;
		if(dep[v]==dep[u]+1&&val)
		{
    
    
			ll res=dfs(v,min(uv-used,val));
			a[i].val-=res;
			a[i^1].val+=res;
			used+=res;
			if(used==uv)
				return used;
		}
	}
	if(used==0)
		dep[u]=-1;
	return used;
}
ll Dinic(int s)
{
    
    
	ll ans=0;
	while(bfs(s))
		ans+=dfs(s,inf);
	return ans;
}
void init()
{
    
    
	cnt=0;
	memset(head,-1,sizeof head);
}
int main()
{
    
    
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	init();
	cin>>n>>m>>e;
	for(int i=1;i<=e;i++)
	{
    
    
		cin>>u>>v;
		u++;v=n+v+1;
		add(u,v,1);
	}
	for(int i=1;i<=n;i++)
		add(1,i+1,1);
	n++;
	for(int i=1;i<=m;i++)
		add(n+i,n+m+1,1);
	t=n+m+1;
	n=t;
	cout<<Dinic(1)<<endl; 
    return 0;
}

Guess you like

Origin blog.csdn.net/WTMDNM_/article/details/108800278