本文共 2903 字,大约阅读时间需要 9 分钟。
为了解决这个问题,我们需要找到从给定矩阵中选出的 N 个数中第 K 大的数的最小值。我们可以使用二分查找来确定这个最小值,并结合最大匹配算法来检查每个中间值是否满足条件。
mid,检查是否存在一种选法,使得选出的 N 个数中至少有 N-K+1 个数小于等于 mid。mid,我们构造一个二分图,其中边的存在条件是矩阵中的元素小于等于 mid。然后使用最大流算法(Dinic算法)来检查是否存在一个足够大的匹配。#include#include #include #include #include using namespace std;class Edge { public: int to; int rev; int capacity; Edge(int to, int rev, int capacity) : to(to), rev(rev), capacity(capacity) {}};vector > graph;int max_flow = 0;void add_edge(int u, int v, int cap) { graph[u].push_back(Edge(v, graph[v].size(), cap)); graph[v].push_back(Edge(u, graph[u].size()-1, 0));}void bfs_level(int s, int t, vector & level) { queue q; level[s] = 0; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (auto& e : graph[u]) { if (level[e.to] == -1 && e.capacity > 0) { level[e.to] = level[u] + 1; q.push(e.to); } } }}void dfs_flow(int u, int t, int flow, vector & ptr, vector & level, vector & ptr_edge) { if (u == t) return flow; for (int i = 0; i < ptr[u]; i++) { int e = graph[u][i]; if (e.capacity > 0 && level[u] < level[e.to]) { int min_flow = min(flow, e.capacity); int result = dfs_flow(e.to, t, min_flow, ptr, level, ptr_edge); if (result > 0) { e.capacity -= result; graph[e.to][ptr_edge[e.to]].capacity += result; return result; } } } return 0;}int max_flow_dinic(int s, int t) { vector level; while (true) { bfs_level(s, t, level); if (level[t] == -1) return max_flow; vector ptr(graph.size()); while (true) { int f = dfs_flow(s, t, INT_MAX, ptr, level, ptr_edge); if (f == 0) break; max_flow += f; } }}int main() { int n, m, k; scanf("%d %d %d", &n, &m, &k); vector > matrix(n, vector (m)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { int val; scanf("%d", &val); matrix[i][j] = val; } } int max_val = INT_MAX; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (matrix[i][j] > max_val) max_val = matrix[i][j]; } } int low = 1, high = max_val, ans = max_val; required = n - k + 1; while (low <= high) { mid = (low + high) >> 1; int size = n + m + 2; graph.resize(size); for (int i = 0; i < size; ++i) { graph[i].clear(); } for (int i = 1; i <= n; ++i) { add_edge(0, i, 1); } for (int j = 1; j <= m; ++j) { add_edge(n+1 + j -1, size-1, 1); } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if (matrix[i-1][j-1] <= mid) { add_edge(i, n+1 + j-1, 1); } } } int f = max_flow_dinic(0, size-1); if (f >= required) { ans = mid; high = mid - 1; } else { low = mid + 1; } } cout << ans << endl; return 0;}
转载地址:http://eail.baihongyu.com/