Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define NDEBUG
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- #define long ll
- #define all(x) begin(x), end(x)
- namespace flow {
- const int SOURCE = 2198;
- const int SINK = 2199;
- const int N = 2200;
- const int INT_INF = 0x3f3f3f3f;
- int c[N][N];
- int f[N][N];
- int d[N];
- int p[N];
- void add_edge(int a, int b, int w) {
- c[a][b] += w;
- }
- int lim;
- bool bfs() {
- memset(d, 0x3f, sizeof d);
- memset(p, 0, sizeof p);
- d[SOURCE] = 0;
- deque<int> q = { SOURCE };
- while (q.size()) {
- int v = q.front();
- q.pop_front();
- for (int u = 0; u < N; ++u) {
- if (c[v][u] - f[v][u] >= lim && d[u] > d[v] + 1) {
- d[u] = d[v] + 1;
- q.push_back(u);
- }
- }
- }
- return d[SINK] < INT_INF;
- }
- int dfs(int v, int min_c) {
- if (v == SINK) {
- return min_c;
- }
- for (; p[v] < N; ++p[v]) {
- int u = p[v];
- if (d[u] == d[v] + 1 && c[v][u] - f[v][u] >= lim) {
- int delta = dfs(u, min(min_c, c[v][u] - f[v][u]));
- if (delta > 0) {
- f[v][u] += delta;
- f[u][v] -= delta;
- return delta;
- }
- }
- }
- return 0;
- }
- void find_flow() {
- int answer = 0;
- for (lim = 1 << 20; lim > 0; lim /= 2) {
- while (bfs()) {
- int cur_flow = dfs(SOURCE, INT_INF);
- while (cur_flow > 0) {
- answer += cur_flow;
- cur_flow = dfs(SOURCE, INT_INF);
- }
- }
- }
- assert(answer >= 0);
- }
- }
- const int N = 2e5 + 5;
- const int K = 7;
- const int TK = 2187;
- int n, k;
- int a[N][K];
- int t[N][K];
- int d[TK][K];
- vector<int> bag[TK];
- vector<int> srt[K];
- int x2_med[K];
- char good[3][3] = {
- { 0, 1, 1 },
- { 1, 1, 1 },
- { 1, 1, 0 }
- };
- int main() {
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cin >> n >> k;
- for (int i = 0; i < n; ++i) {
- for (int j = 0; j < k; ++j) {
- cin >> a[i][j];
- srt[j].push_back(a[i][j]);
- }
- }
- for (int i = 0; i < k; ++i) {
- sort(all(srt[i]));
- x2_med[i] = srt[i][n / 2 - 1] + srt[i][n / 2];
- }
- for (int i = 0; i < n; ++i) {
- for (int j = 0; j < k; ++j) {
- if (2 * a[i][j] < x2_med[j]) {
- t[i][j] = 0;
- } else if (2 * a[i][j] == x2_med[j]) {
- t[i][j] = 1;
- } else {
- t[i][j] = 2;
- }
- }
- assert(t[i][0] != 1);
- int id = 0;
- for (int j = k - 1; j >= 0; --j) {
- id = 3 * id + t[i][j];
- }
- bag[id].push_back(i);
- }
- for (int i = 0; i < TK; ++i) {
- int x = i;
- for (int j = 0; j < k; ++j) {
- d[i][j] = x % 3;
- x /= 3;
- }
- }
- for (int i = 0; i < TK; ++i) {
- if (bag[i].empty()) {
- continue;
- }
- for (int j = i + 1; j < TK; ++j) {
- if (bag[j].empty()) {
- continue;
- }
- bool br = false;
- for (int bit = 0; bit < k; ++bit) {
- if (!good[d[i][bit]][d[j][bit]]) {
- br = true;
- break;
- }
- }
- if (br) {
- continue;
- }
- if (d[i][0] == 0) {
- assert(d[j][0] == 2);
- flow::add_edge(i, j, (int)1e9);
- } else {
- assert(d[j][0] == 0);
- flow::add_edge(j, i, (int)1e9);
- }
- }
- }
- for (int i = 0; i < TK; ++i) {
- if (bag[i].empty()) {
- continue;
- }
- if (d[i][0] == 0) {
- flow::add_edge(flow::SOURCE, i, (int)bag[i].size());
- } else {
- flow::add_edge(i, flow::SINK, (int)bag[i].size());
- }
- }
- flow::find_flow();
- vector<pair<int, int>> answer;
- for (int v = 0; v < TK; ++v) {
- for (int u = 0; u < TK; ++u) {
- while (flow::f[v][u]-- > 0) {
- answer.emplace_back(bag[v].back(), bag[u].back());
- bag[v].pop_back();
- bag[u].pop_back();
- }
- }
- }
- if ((int)answer.size() == n / 2) {
- cout << "YES\n";
- for (auto &e : answer) {
- cout << e.first + 1 << ' ' << e.second + 1 << '\n';
- }
- } else {
- cout << "NO\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement