二分图最大匹配
https://www.luogu.com.cn/problem/P3386
左端点到右端点连容量为 \(1\) 的边,超级源点到每个左端点连容量为 \(1\) 的边,每个右端点到超级汇点连容量为 \(1\) 的边,求最大流即可。
代码
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 9e18;
void solve(){
int L,R,m;
cin >> L >> R >> m;
int n = L+R;
vector<vector<array<ll,3>>> adj(n+3);
auto add = [&](int u,int v,ll w){
adj[u].push_back({w,(int)adj[v].size(),v});
adj[v].push_back({0,(int)adj[u].size()-1,u});
};
for (int i=0;i<m;i++){
int u,v;
cin >> u >> v;
add(u,v+L,1);
}
int s = n+1;
int t = n+2;
for (int i=1;i<=L;i++){
add(s,i,1);
}
for (int i=L+1;i<=n;i++){
add(i,t,1);
}
int N = n+2;
vector<int> cur,depth;
auto bfs = [&](){
depth = vector<int>(N+1,-1);
queue<int> q;
depth[s] = 0;
q.push(s);
while (!q.empty()){
int u = q.front();
q.pop();
for (auto& [w,rev,v]:adj[u]){
if (w>0 && depth[v]==-1){
depth[v] = depth[u]+1;
q.push(v);
}
}
}
return depth[t]!=-1;
};
ll mxf = 0;
function<ll(int,ll)> dfs = [&](int u,ll mf){
if (u==t) return mf;
ll sum = 0;
int len = adj[u].size();
for (int& i=cur[u];i<len;i++){
auto& [w,rev,v] = adj[u][i];
if (w>0 && depth[v]==depth[u]+1){
ll f = dfs(v,min(mf,w));
w -= f;
adj[v][rev][0] += f;
sum += f;
mf -= f;
if (mf==0) break;
}
}
return sum;
};
while (bfs()){
cur = vector<int>(N+1);
mxf += dfs(s,INF);
}
cout << mxf << '\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号