1 条题解
-
0
题解何意?
实际上 就是 的中位数,我们只关心数与 的大小关系。设 为 , 为 , 为 ,那我们相当于要解决如下问题:
- 有 个长度为 的 串。你需要将每个 替换为 ,再将这 个串匹配,使得匹配的两个串对应位不同。问是否存在完美匹配。
考虑最大流,直接暴力对 种串建图。发现保证了 互不相同,那么可以将所有串分为两部分,建成二分图。
以源点一侧为例,若当前这个串有 ,那么将最低的那个 替换成 ,连一条流量为 的边。否则,将这个串与对应的能匹配的串连边。汇点一侧同理。这样总边数为 。用 Dinic 求解最大流即可做到 ,可以通过。当然可以像楼下说的那样用 HLPP 做到 ,但是太没必要了。
对于构造方案,直接顺着流量推即可。
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int MAXN = 2e5 + 10; const int MAXM = 5e3; const int MAXK = 1460; const int inf = 0x3f3f3f3f; struct edge { int v, c, nxt; edge(int v = 0, int c = 0, int nxt = 0) : v(v), c(c), nxt(nxt) {} } e[MAXM << 1]; int head[MAXK], tot = 1; inline void add(int u, int v, int c) { e[++tot] = edge(v, c, head[u]), head[u] = tot; e[++tot] = edge(u, 0, head[v]), head[v] = tot; } int lst[MAXK], lvl[MAXK]; inline bool bfs(int s, int t) { memset(lvl, 0xff, sizeof lvl); queue<int> q; q.emplace(s), lvl[s] = 0; for (int u; !q.empty(); ) { u = q.front(), q.pop(), lst[u] = head[u]; for (int _ = head[u]; _; _ = e[_].nxt) { int v = e[_].v, c = e[_].c; if (c && !~lvl[v]) lvl[v] = lvl[u] + 1, q.emplace(v); } } return ~lvl[t]; } int dfs(int u, int t, int f = inf) { if (u == t) return f; int res = 0; for (int &_ = lst[u]; _; _ = e[_].nxt) { int v = e[_].v, c = e[_].c; if (!c || lvl[v] != lvl[u] + 1) continue; int x = dfs(v, t, min(f, c)); e[_].c -= x, e[_ ^ 1].c += x, f -= x, res += x; } return res; } inline int dinic(int s, int t) { int res = 0; for (; bfs(s, t); res += dfs(s, t)); return res; } int n, m, B, S, T, a[7][MAXN], b[7][MAXN]; vector<int> fs[729], ft[729]; int main() { scanf("%d%d", &n, &m), B = 1; for (int i = 1; i < m; i++) B *= 3; S = B << 1, T = S | 1; for (int i = 1; i <= n; i++) { for (int j = 0; j < m; j++) scanf("%d", &a[j][i]); } memcpy(b, a, sizeof a); for (int j = 0; j < m; j++) sort(b[j] + 1, b[j] + n + 1); for (int i = 1; i <= n; i++) { int k = n >> 1, x = 0; for (int j = 0; j < m; j++) { x *= 3; if (a[j][i] >= b[j][k + 1]) ++x, (a[j][i] <= b[j][k]) && ++x; } if (x < B) fs[x].emplace_back(i); else ft[x - B].emplace_back(i); } for (int i = 0; i < B; i++) { if (!fs[i].empty()) add(S, i, fs[i].size()); if (!ft[i].empty()) add(B + i, T, ft[i].size()); int p = 0; for (int j = 1, x = i; x; x /= 3, j *= 3) { if (x % 3 == 2) { p = j; break; } } if (p) { add(i, i - p, inf), add(B + i - p, B + i, inf); add(i, i - p - p, inf), add(B + i - p - p, B + i, inf); } } for (int i = 0; i < 1 << m - 1; i++) { int x = 0, y = 0; for (int j = m - 1; ~j; j--) x *= 3, y *= 3, (i >> j & 1) ? ++x : ++y; add(x, y, inf); } if (dinic(S, T) != n >> 1) return puts("NO"), 0; puts("YES"); for (int i = B - 1; ~i; i--) { int p = 0; for (int j = 1, x = i; x; x /= 3, j *= 3) { if (x % 3 == 2) { p = j; break; } } if (!p) continue; for (int _ = head[i]; _; _ = e[_].nxt) { int v = e[_].v, c = e[_ ^ 1].c; if (v != i - p && v != i - p - p) continue; for (; c--; fs[v].emplace_back(fs[i].back()), fs[i].pop_back()); } for (int _ = head[B + i]; _; _ = e[_].nxt) { int v = e[_].v - B, c = e[_].c; if (v != i - p && v != i - p - p) continue; for (; c--; ft[v].emplace_back(ft[i].back()), ft[i].pop_back()); } } for (int i = 0; i < 1 << m - 1; i++) { int x = 0, y = 0; for (int j = m - 2; ~j; j--) x *= 3, y *= 3, (i >> j & 1) ? ++x : ++y; for (; !fs[x].empty() || !ft[y].empty(); ) { printf("%d %d\n", fs[x].back(), ft[y].back()); fs[x].pop_back(), ft[y].pop_back(); } } }
- 1
信息
- ID
- 10291
- 时间
- 3000ms
- 内存
- 512MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者