Submission #1043230

#TimeUsernameProblemLanguageResultExecution timeMemory
1043230model_codeMake them Meet (EGOI24_makethemmeet)C++17
84.83 / 100
2481 ms3820 KiB
#include <bits/stdc++.h>

using namespace std;
using int64 = int64_t;

constexpr int INF = (int) 1e9;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    vector<vector<int>> d(n, vector<int>(n, INF));
    for (int i = 0; i < n; ++i) d[i][i] = 0;
    for (int i = 0; i < m; ++i) {
      int a, b;
      cin >> a >> b;
      assert(d[a][b] == INF);
      d[a][b] = d[b][a] = 1;
    }
    for (int k = 0; k < n; ++k)
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
          d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

    vector<vector<bool>> can(n, vector<bool>(n, false));
    for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) if (i != j) can[i][j] = true;
    vector<vector<int>> res;
    mt19937 rng(57);
    vector<double> scores = vector<double>(n);
    scores[n - 1] = 1;
    for (int i = n - 2; i >= 0; --i) scores[i] = scores[i + 1] + (n - i);
    vector<int> c(n);
    vector<bool> avail(n, true);
    vector<tuple<double, int, int>> cands;
    vector<int> order(n);
    double BONUS = 5;
    double BONUS2 = 3;
    while (true) {
      bool any = false;
      for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) if (can[i][j]) any = true;
      if (!any) break;
      iota(c.begin(), c.end(), 0);
      avail.assign(n, true);
      iota(order.begin(), order.end(), 0);
      while (true) {
        shuffle(order.begin(), order.end(), rng);
        cands.clear();
        for (int ii = 0; ii < n; ++ii) {
          int i = order[ii];
          if (!avail[i]) continue;
          for (int jj = ii + 1; jj < n; ++jj) {
            int j = order[jj];
            if (!avail[j] || d[i][j] != 1) continue;
            double score = 0;
            if (can[i][j]) score += BONUS * scores[1];
            for (int k = 0; k < n; ++k) if (k != i && k != j) {
              if (can[i][k] && !can[j][k]) score -= scores[d[i][k]] - scores[d[j][k]];
              if (can[j][k] && !can[i][k]) score -= scores[d[j][k]] - scores[d[i][k]];
            }
            cands.emplace_back(-score, i, j);
          }
          {
            bool ok = true;
            double score = 0;
            int cnt_in = 0;
            int cnt_out = 0;
            for (int j1 = 0; j1 < n; ++j1) if (d[i][j1] == 1) {
              if (!avail[j1]) { ok = false; break; }
              if (can[i][j1]) ++cnt_in; else ++cnt_out;
              for (int j2 = j1 + 1; j2 < n; ++j2) if (d[i][j2] == 1) {
                if (d[j1][j2] == 1) { ok = false; break; }
                if (can[j1][j2]) score += BONUS2 * scores[1];
              }
            }
            if (!ok) continue;
            if (cnt_in) score -= BONUS2 * scores[1] * cnt_out;
            for (int k = 0; k < n; ++k) if (d[i][k] >= 2) {
              cnt_in = 0;
              cnt_out = 0;
              for (int j1 = 0; j1 < n; ++j1) if (d[i][j1] == 1) {
                if (can[k][j1]) ++cnt_in; else ++cnt_out;
              }
              if (cnt_in) {
                score += BONUS2 * scores[1] * (cnt_in - 1);
              }
              if (can[k][i]) {
                score -= BONUS2 * scores[1] * (cnt_out + cnt_in);
              }
            }
            cands.emplace_back(-score, i, -1);
          }
        }

        sort(cands.begin(), cands.end());
        for (auto [bs, bi, bj]: cands) {
          if (bj < 0) {
            bool ok = avail[bi];
            for (int j1 = 0; j1 < n; ++j1) if (d[bi][j1] == 1) {
              if (!avail[j1]) ok = false;
            }
            if (!ok) continue;
            //cerr << "Using spoke at " << bi << ", score = " << bs << "\n";
            avail[bi] = false;
            bool h = false;
            for (int j1 = 0; j1 < n; ++j1) if (d[bi][j1] == 1) {
              avail[j1] = false;
              c[j1] = c[bi];
              if (can[bi][j1]) h = true;
              for (int j2 = j1 + 1; j2 < n; ++j2) if (d[bi][j2] == 1) {
                can[j1][j2] = false;
                can[j2][j1] = false;
              }
            }
            if (h) {
              for (int j1 = 0; j1 < n; ++j1) if (d[bi][j1] == 1) {
                can[bi][j1] = true;
                can[j1][bi] = true;
              }
            }
            for (int k = 0; k < n; ++k) if (k != bi && d[bi][k] != 1) {
              bool center = can[bi][k];
              bool spoke = false;
              for (int j1 = 0; j1 < n; ++j1) if (d[bi][j1] == 1 && can[j1][k]) spoke = true;
              can[bi][k] = spoke;
              can[k][bi] = spoke;
              for (int j1 = 0; j1 < n; ++j1) if (d[bi][j1] == 1) {
                can[j1][k] = center;
                can[k][j1] = center;
              }
            }
          } else {
            if (avail[bi] && avail[bj]) {
              //cerr << "Using edge " << bi << "-" << bj << ", score = " << bs << "\n";
              if (uniform_int_distribution<int>(0, 10)(rng) == 0) continue;
              c[bi] = c[bj];
              avail[bi] = false;
              avail[bj] = false;
              can[bi][bj] = can[bj][bi] = false;
              for (int k = 0; k < n; ++k) if (k != bi && k != bj) {
                if (can[bi][k] && !can[bj][k]) {
                  can[bj][k] = true;
                  can[k][bj] = true;
                  can[bi][k] = false;
                  can[k][bi] = false;
                } else if (can[bj][k] && !can[bi][k]) {
                  can[bj][k] = false;
                  can[k][bj] = false;
                  can[bi][k] = true;
                  can[k][bi] = true;
                }
              }
            }
          }
        }
        break;
      }
      res.push_back(c);
      //for (int i = 0; i < n; ++i) {
      //  for (int j = 0; j < n; ++j) if (can[i][j]) cerr << '+'; else cerr << '-';
      //  cerr << '\n';
      //}
      //cerr << endl;
    }
    printf("%d\n", res.size());
    for (const auto& v : res) {
      for (auto x : v) printf("%d ", x);
      printf("\n");
    }
    return 0;
}

Compilation message (stderr)

Main.cpp: In function 'int main()':
Main.cpp:165:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wformat=]
  165 |     printf("%d\n", res.size());
      |             ~^     ~~~~~~~~~~
      |              |             |
      |              int           std::vector<std::vector<int> >::size_type {aka long unsigned int}
      |             %ld
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...