【图论】网络流解决二分图最大匹配量问题
在二分图左边添加一个源点,该源点和二分图中一半的所有结点相连,同时建立一个汇点,将该汇点与另一半中的每一个点连边。
若bfs返回值为true,则说明仍具有增广路,也就是还可以增加匹配量;否则的话,无法扩大匹配数。
题目链接Acwing 2175
#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;
}