B3605 题解
EuphoricStar · · 题解
思路
本题可转化为最大流问题。
设源点为
然后源点向每个左侧点连一条容量为
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1020, maxm = 511000, inf = 0x3f3f3f3f;
int n, nl, nr, m, s, t, head[maxn], len;
struct edge {
int from, to, next, cap, flow;
} edges[maxm];
void add_edge(int u, int v, int c, int f) {
edges[++len].from = u;
edges[len].to = v;
edges[len].next = head[u];
edges[len].cap = c;
edges[len].flow = f;
head[u] = len;
}
struct Dinic {
bool vis[maxn];
int d[maxn], cur[maxn];
void add(int u, int v, int c) {
add_edge(u, v, c, 0);
add_edge(v, u, 0, 0);
}
bool bfs() {
memset(vis, 0, sizeof(vis));
queue<int> q;
d[s] = 0;
vis[s] = 1;
q.push(s);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = head[u]; i; i = edges[i].next) {
edge e = edges[i];
if (!vis[e.to] && e.cap > e.flow) {
vis[e.to] = 1;
d[e.to] = d[u] + 1;
q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int u, int a) {
if (u == t || !a) {
return a;
}
int flow = 0, f;
for (int &i = cur[u]; i; i = edges[i].next) {
edge &e = edges[i];
if (d[u] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
e.flow += f;
edges[i ^ 1].flow -= f;
flow += f;
a -= f;
if (!a) {
break;
}
}
}
return flow;
}
int solve() {
int flow = 0;
while (bfs()) {
for (int i = 1; i <= n; ++i) {
cur[i] = head[i];
}
flow += dfs(s, inf);
}
return flow;
}
} solver;
int main() {
scanf("%d%d%d", &nl, &nr, &m);
s = 1;
t = n = nl + nr + 2;
len = 1;
for (int i = 1; i <= nl; ++i) {
solver.add(s, i + 1, 1);
}
for (int i = 1; i <= nr; ++i) {
solver.add(i + nl + 1, t, 1);
}
while (m--) {
int u, v;
scanf("%d%d", &u, &v);
solver.add(u + 1, v + nl + 1, 1);
}
printf("%d", solver.solve());
return 0;
}