1 条题解

  • 0
    @ 2026-8-4 1:10:14

    首先第一想法,就是枚举三个顶点,但是因为会有重复的顶点干扰,所以需要写一个 dfs 回溯一些方案。

    但是完全没必要!因为只需要求出一半的三角形,直接枚举三个顶点寻找,能找多少是多少,没必要回溯方案。因为若当前选择的三角形影响到后续选择,依然没关系,只需要保证最后能找到一半三角形即可,容错率非常大!

    这样复杂度是 O(63×n3)O(6^3\times n^3),但是完全没关系,跑的非常快!其实还有优化空间,枚举第三个顶点时用前两个顶点的 bitset 并集即可。

    while (1) {
      _for(i, 1, 6 * n) id[i] = i, vd[i] = 0;
      shuffle(id + 1, id + 6 * n + 1, rnd);
      vector<pair<int, pair<int, int>> > ans;
      _for(i, 1, 6 * n) {
        if (vd[id[i]]) continue;
        _for(j, i + 1, 6 * n) {
          if (vd[id[i]] || vd[id[j]] || !vis[{id[i], id[j]}]) continue;
          _for(k, j + 1, 6 * n) {
            if (vd[id[i]] || vd[id[j]] || vd[id[k]]) continue;
            if (!vis[{id[i], id[k]}] || !vis[{id[j], id[k]}]) continue;
            ans.push_back({id[i], {id[j], id[k]}});
            vd[id[i]] = vd[id[j]] = vd[id[k]] = 1;
            if (ans.size() == n) break;
          }
          if (ans.size() == n) break;
        }
        if (ans.size() == n) break;
      }
      if (ans.size() == n) {
        for (auto v : ans) cout << v.first << ' ' << v.second.first << ' ' << v.second.second << endl;
        break;
      } 
    }
    
    • 1

    信息

    ID
    12543
    时间
    4000ms
    内存
    6000MiB
    难度
    10
    标签
    递交数
    2
    已通过
    0
    上传者