算法思路
定义两类点:奇点和偶点
首先从起点出发,并设为偶点。在队列中维护偶点,每次取出一个偶点进行增广
- 遇到未访问过的点 v:记录路径 pre[v]=u,并设为奇点
(1)如果 v 未匹配,那么就找到了增广路,通过pre数组,更新点的类型与当前的匹配情况(更新 match 数组)。然后直接返回
(2)如果 v 已经匹配了,那么就将与 v 匹配的点 match[v] 放入队列进行增广 - 遇到访问过的点 v :
(1)v 是偶点,那么就找到了一个奇环,将这个环缩成一个点,并且将环上的所有奇点变成偶点,放入队列中增广
(2)v 是奇点,直接跳过没有影响
UOJ 79. 一般图最大匹配
思路:最大匹配模板题,建完图之后直接跑带花树即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
namespace MaxMatching
{
const int MAXN=510,MAXM=2e5;
int match[MAXN],type[MAXN],fa[MAXN],pre[MAXN];
int times,visit[maxn],maxvex;
queue<int> q;
int head[MAXN],ecnt;
struct Edge
{
int nxt,to;
}edges[MAXM<<1];
inline void add(int u,int v)
{
edges[++ecnt].to=v;
edges[ecnt].nxt=head[u];
head[u]=ecnt;
}
inline void init(int n)
{
maxvex=n;
for(int i=0;i<=n;++i)
head[i]=-1,match[i]=visit[i]=pre[i]=0;
ecnt=-1;
}
inline int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
inline int lca(int u,int v)
{
times++;
while(visit[u]!=times)
{
if(u)
{
u=find(u);
if(visit[u]==times) return u;
visit[u]=times;
if(match[u]!=0) u=find(pre[match[u]]);
else u=0;
}
swap(u,v);
}
return u;
}
inline void blossom(int x,int y,int k)
{
while(find(x)!=k)
{
pre[x]=y;
int z=match[x];
if(type[z]==1)
{
type[z]=0;
q.push(z);