1 条题解
-
0
自动搬运
来自洛谷,原作者为

EuphoricStar
Remember.搬运于
2025-08-24 21:13:50,当前版本为作者最后更新于2021-07-05 07:06:59,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
思路
本题可转化为最大流问题。
设源点为 ,汇点为 ,左侧点编号为 ~ ,右侧点编号为 ~ 。
然后源点向每个左侧点连一条容量为 的边,每个右侧点向汇点连一条容量为 的边,左侧点和右侧点按照输入的边连一条容量为 的边,然后跑一遍 Dinic,此时最大流便是答案。
代码
#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; }
- 1
信息
- ID
- 6855
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- (无)
- 递交数
- 0
- 已通过
- 0
- 上传者