Title

【图论】网络流解决二分图最大匹配量问题

在二分图左边添加一个源点,该源点和二分图中一半的所有结点相连,同时建立一个汇点,将该汇点与另一半中的每一个点连边。
若bfs返回值为true,则说明仍具有增广路,也就是还可以增加匹配量;否则的话,无法扩大匹配数。
题目链接Acwing 2175
image

#include <bits/stdc++.h>
#define MEM(a,x) memset(a,x,sizeof(a))
#define W(a) while(a)
#define gcd(a,b) __gcd(a,b)
#define pi acos(-1.0)
#define PII pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define MAX 1000005
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define lowbit(x) (x&-x)
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int MAXN = 1e5+100, N = 400;
struct edge{
	int u,v;
	int cap,flow;
	int nxt;
}edges[MAXN];
int idx,h[MAXN];
void add(int a,int b,int c)
{
	edges[idx]={a,b,c,0,h[a]};
	h[a]=idx++;
}
int n,m,S,T,to[MAXN],cur[N],dis[N];
inline int dfs(int u,int res)
{
	if(u==T||res<=0)
	  return res;
	  
	int f = 0,flow = 0;
	for(int i=cur[u];~i;i=edges[i].nxt)
	{
		cur[u]=i;
		int v = edges[i].v, u = edges[i].u;
		if(edges[i].cap>edges[i].flow&&dis[v]==dis[u]+1)
		{
			f = dfs(v,min(res,edges[i].cap-edges[i].flow));
			edges[i].flow+=f;
			edges[i^1].flow-=f;
			flow+=f;
			res-=f;
		        to[u]=v;
		}
	}
	
	return flow;
}
inline bool bfs()
{
	memset(dis,-1,sizeof(dis));
	queue<int> q;
	q.push(S);
	dis[S]=0;
	while(q.size())
	{
		int t = q.front();
		q.pop();
		cur[t] = h[t];
		for(int i=h[t];~i;i=edges[i].nxt)
		{
			int v = edges[i].v,u = edges[i].u;
                        if(dis[v]!=-1||edges[i].flow>=edges[i].cap) continue;
                            dis[v] = dis[u] + 1;
                            q.push(edges[i].v);
		}
	}
	if(dis[T]==-1)
	   return 0;
	return 1;
}
void Dicnic()
{
	int ansflow = 0;
	int cs = 0;
	int maxflow = 0;
	for(int i = 1;i<=n;i++)
	    cur[i] = h[i];
	while(bfs())
	{
		int p = dfs(S,200);
		cs++;
		ansflow+=p;
		maxflow=max(maxflow,p);
	}
	cout<<ansflow<<endl;
}
int main()
{
	memset(h,-1,sizeof(h));
	memset(to,-1,sizeof(to));
	n = read(),m = read();
	S = 0, T = n + m + 1;
	int a,b;
	for(int i=1;i<=n;i++)
	   add(S,i,1),add(i,S,0); 
	while(1)
	{
		a = read(), b = read();
		if(a==-1&&b==-1) break;
		add(a,b,1);add(b,a,0);
	}
	for(int i=n+1;i<=n+m;i++)
	   add(i,T,1),add(T,i,0);
	
	Dicnic();
	for(int i=2*n;i<=idx-2*m-1;i+=2)
	    if(edges[i].flow==edges[i].cap)
	       cout<<edges[i].u<<" "<<edges[i].v<<endl;
    return 0;
}

posted @ 2021-11-01 19:28  BeautifulWater  阅读(79)  评论(0编辑  收藏  举报