P3386 【模板】二分图最大匹配 题解
写在前面:请管理员大大仔细审一下,不想再因为因举报核查被禁专栏了QAQ。谢谢!
前置芝士:网络最大流(文中使用了 dinic 算法)。不会的话请先出门右拐,慢走不送。
思路
虽然题目明确写了这道题是二分图最大匹配,但是我们需要把思路放开,所以这道题可以使用网络流。
众所周知,网络流的实现需要一个连通图,并且它里面应该包含源点和汇点。显然,这道题已经给出了很多个点和很多条边,但唯独没有给出源点与汇点。所以我们需要先建立超级源点和超级汇点:
- 超级源点:由于(按照作者习惯)编号 \(1\) 到编号 \(n+m\) 都被占了,所以源点的编号为 \(0\)。然后再将源点和所有左部点用长为 \(1\) 的边连起来。至于为什么要这样做,后面会说;
- 超级汇点:由于(按照作者习惯)编号 \(1\) 到编号 \(n+m\) 都被占了,所以汇点的编号为 \(n+m+1\)。然后再将汇点和所有右部点用长为 \(1\) 的边连起来。至于为什么要这样做,后面也会说。
顺便说一句,建图的时候,左部点和右部点之间的边长度随意,原因后面依然会说。
建完图后跑一遍网络流即可。
证明
思路已经说完了,现在说明一下唯一(也许吧)的疑点,那就是为什么要让所有与源点、汇点相连的边长都是 \(1\)。
我们从题意入手。这道题是个二分图最大匹配,它有一个限制:所有点只能用一次,所有边只能用一次。所以,源点到左部点的边长为 \(1\),让每个左部点所在的路径只能走一次;汇点到右部点的边长为 \(1\),让每个右部点所在的路径也只能走一次。这里为 \(1\) 的边长,可以理解为一种限制,同时也满足了计数的需求。
顺便说一句,建图的时候,左部点和右部点之间的边长度随意,是因为该限制的已经限制了,该计数的已经能计了,所以长度只要不爆掉就行。
代码
最后就是代码时刻了。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,e,s,t,x,y,z,ans,cnt=1,dist[1000000],now[1000000],head[1000000];
struct node
{
int to;
int value;
int next;
}a[1000000];
void addedge(int x,int y,int z)
{
a[++cnt].to=y;
a[cnt].value=z;
a[cnt].next=head[x];
head[x]=cnt;
}
int bfs()
{
for(int i=1;i<=t;++i) dist[i]=0x7fffffff;
queue<int>q;
q.push(s);
now[s]=head[s];
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=a[i].next)
{
int y=a[i].to;
if(a[i].value>0&&dist[y]==0x7fffffff)
{
q.push(y);
now[y]=head[y];
dist[y]=dist[x]+1;
if(y==t) return 1;
}
}
}
return 0;
}
int dfs(int x,int sum)
{
if(x==t) return sum;
int k,res=0;
for(int i=now[x];i&∑i=a[i].next)
{
now[x]=i;
int y=a[i].to;
if(a[i].value>0&&(dist[y]==dist[x]+1))
{
k=dfs(y,min(sum,a[i].value));
if(k==0) dist[y]=0x7fffffff;
a[i].value-=k;
a[i^1].value+=k;
res+=k;
sum-=k;
}
}
return res;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
cin>>n>>m>>e;
for(int i=1;i<=e;++i)
{
cin>>x>>y;
addedge(x,y+n,0x7fffffff);
addedge(y+n,x,0);
}
t=n+m+1;
for(int i=1;i<=n;++i)
{
addedge(s,i,1);
addedge(i,s,0);
}
for(int i=n+1;i<t;++i)
{
addedge(i,t,1);
addedge(t,i,0);
}
while(bfs())
{
ans+=dfs(s,0x7fffffff);
}
cout<<ans;
return 0;
}
完结撒花。

浙公网安备 33010602011771号