传送门 思路:求男孩和女孩的配对个数。裸的匈牙利算法,用dinic建图直接求最大流也行。
匈牙利算法
大佬博客
using namespace std;
int G[maxn][maxn], used[maxn], vis[maxn], m;
bool Find(int u) {
for(int i = 1 ; i <= m ; i++) {
if(!vis[i] && G[u][i]) {
///vis[i]表示i男生还没有被别的女生选走
vis[i] = 1;
if(!used[i] || Find(used[i])) {
///如果女生used[i]没有选男生i作伴或者女生used[i]选了男生i,她放弃男生i并且另外找到了自己的伴
///当前还可以挪出来位置
used[i] = u;///就让男生i与女生u作伴
return true;
}
}
}
return false;
}///该函数判断女生能不能找到伴
int main() {
int k, n, i, a, b, ans;
while(cin >> k >> n >> m) { ///n 女生 m 男生
ans = 0;
mem(G, 0);
while(k--) {
cin >> a >> b;
G[a][b] = 1;///G[a][b]表示女生a愿意与男生b作伴
}///used[i]表示i男生与used[i]女生作伴
mem(used, 0);
for(i = 1 ; i <= n ; i++) {
mem(vis, 0);
if(Find(i))
ans++;
}
cout << ans << endl;
}
return 0;
}
dinic最大流建图
using namespace std;
int n, m; //点数、边数
int s, t; //原点、汇点
struct node {
int v, next;
int cap;
} mp[maxn * 10];
int pre[maxn], dis[maxn], cur[maxn]; //cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表
int cnt, edge_num = 1;
int vis[maxn], Dis[maxn];
int head1[maxn], head[maxn];
void add(int u, int v, int w) { //加边
mp[++edge_num].v = v;
mp[edge_num].cap = w;
mp[edge_num].next = pre[u];
pre[u] = edge_num;
}
bool bfs(int s) { //建分层图
mem(dis, -1);
queue<int>q;
while(!q.empty())
q.pop();
q.push(s);
dis[s] = 0;
int u, v;
while(!q.empty()) {
u = q.front();
q.pop();
for(int i = pre[u]; i != -1; i = mp[i].next) {
v = mp[i].v;
if(dis[v] == -1 && mp[i].cap > 0) {
dis[v] = dis[u] + 1;
q.push(v);
if(v == t)
return 1;
}
}
}
return dis[t] != -1;
}
int dfs(int u, int cap) { //寻找增广路
if(u == t || cap == 0)
return cap;
int res = 0, f;
for(int &i = cur[u]; i != -1; i = mp[i].next) {
int v = mp[i].v;
if(dis[v] == dis[u] + 1 && mp[i].cap > 0) {
f = dfs(v, min(cap, mp[i].cap));
mp[i].cap -= f;
mp[i ^ 1].cap += f;
res += f;
cap -= f;
if(cap == 0) break;
}
}
if(cap > 0)
dis[u] = -1;
return res;
}
int dinic( ) {
int ans = 0;
while(bfs(s)) {
memcpy(cur, pre, sizeof pre);
ans += dfs(s, inf);
}
return ans;
}
int main() {
int k;
while(cin >> k >> m >> n ) {
mem(pre, -1);
mem(mp,0);
edge_num = 1;
s = n + m + 1, t = s + 1;
for(int i = 1; i <= m; i++) {
add(s, i, 1);
add(i, s, 0);
}
for(int i = 1 + m; i <= n + m; i++) {
add(i, t, 1);
add(t, i, 0);
}
for(int i = 1; i <= k; i++) {
int u, v;
cin >> u >> v;
add(u, v + m, 1);
add(v + m, u, 0);
}
cout << dinic() << endl;
}
return 0;
}