增广路算法O(nm)
struct augment_path {
vector<vector<int> > g;
vector<int> pa; // 匹配
vector<int> pb;
vector<int> vis; // 访问
int nn, mm; // 两个点集中的顶点数量
int dfn; // 时间戳记
int res; // 匹配数
augment_path(int _n, int _m) : nn(_n), mm(_m)
{
pa = vector<int>(nn, -1);
pb = vector<int>(mm, -1);
vis = vector<int>(nn);
g.resize(nn);
res = 0;
dfn = 0;
}
void add(int from, int to)
{
g[from].push_back(to);
}
bool dfs(int v)
{
vis[v] = dfn;
for (int i=0;i<g[v].size();i++)
{
int u=g[v][i];
if (pb[u] == -1)
{
pb[u] = v;
pa[v] = u;
return true;
}
}
for(int i=0;i<g[v].size();i++)
{
int u=g[v][i];
if (vis[pb[u]] != dfn && dfs(pb[u]))
{
pa[v] = u;
pb[u] = v;
return true;
}
}
return false;
}
int solve()
{
while (true)
{
dfn++;
int cnt=0;
for(int i = 0;i<nn;i++)
if (pa[i]==-1&&dfs(i))
cnt++;
if(cnt==0)
break;
res += cnt;
}
return res;
}
};