ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • knuth_x
    232's competitive-programming templates. 2024. 9. 12. 19:59
    namespace knuth_x {
      struct Node {
        int id;
        int siz;
        Node* leader;
        Node* up;
        Node* down;
        Node* left;
        Node* right;
    
        Node(int id = -1) : id(id), siz(0), leader(nullptr), up(nullptr), down(nullptr), left(nullptr), right(nullptr) {
          void(0);
        }
      };
    
      void cover(Node* leader) {
        leader->right->left = leader->left;
        leader->left->right = leader->right;
        for (Node* i = leader->down; i != leader; i = i->down) {
          for (Node* j = i->right; j != i; j = j->right) {
            j->up->down = j->down;
            j->down->up = j->up;
            j->leader->siz -= 1;
          }
        }
      }
    
      void uncover(Node* leader) {
        leader->right->left = leader;
        leader->left->right = leader;
        for (Node* i = leader->up; i != leader; i = i->up) {
          for (Node* j = i->left; j != i; j = j->left) {
            j->up->down = j;
            j->down->up = j;
            j->leader->siz += 1;
          }
        }
      }
    
      bool search(Node* head, std::vector<int>& res) {
        if (head->right == head) {
          return true;
        }
        Node* ptr = nullptr;
        for (Node* i = head->right; i != head; i = i->right) {
          if (i->siz == 0) {
            return false;
          }
          if (!ptr || ptr->siz > i->siz) {
            ptr = i;
          }
        }
        cover(ptr);
        for (Node* i = ptr->down; i != ptr; i = i->down) {
          res.push_back(i->id);
          for (Node* j = i->right; j != i; j = j->right) {
            cover(j->leader);
          }
          if (search(head, res)) {
            return true;
          }
          res.pop_back();
          for (Node* j = i->left; j != i; j = j->left) {
            uncover(j->leader);
          }
        }
        uncover(ptr);
        return false;
      }
    
      std::vector<int> solve(const std::vector<std::vector<bool>>& mat) { // empty vector if no solution...
        assert(!mat.empty());
        int n = int(mat[0].size());
        assert(n > 0);
        for (const auto& vec : mat) {
          assert(int(vec.size()) == n);
        }
        std::vector<Node> leaders(n);
        Node head;
        head.left = &leaders.back();
        head.right = &leaders.front();
        for (int i = 0; i < n; ++i) {
          leaders[i].up = &leaders[i];
          leaders[i].down = &leaders[i];
          leaders[i].left = (i == 0 ? &head : &leaders[i - 1]);
          leaders[i].right = (i == n - 1 ? &head : &leaders[i + 1]);
        }
        std::vector<Node*> nodes;
        for (int i = 0; i < int(mat.size()); ++i) {
          Node* last = nullptr;
          for (int j = 0; j < n; ++j) {
            if (!mat[i][j]) {
              continue;
            }
            Node* new_node = new Node(i);
            leaders[j].siz += 1;
            new_node->up = leaders[j].up;
            new_node->down = &leaders[j];
            new_node->leader = &leaders[j];
            leaders[j].up->down = new_node;
            leaders[j].up = new_node;
            if (last) {
              new_node->left = last;
              new_node->right = last->right;
              new_node->right->left = new_node;
              new_node->left->right = new_node;
            } else {
              new_node->left = new_node;
              new_node->right = new_node;
            }
            nodes.push_back(last = new_node);
          }
        }
        std::vector<int> res;
        search(&head, res);
        for (const auto& ptr : nodes) {
          delete ptr;
        }
        return res;
      }
    } // namespace knuth_x

    '232's competitive-programming templates.' 카테고리의 다른 글

    TwoSat  (0) 2024.09.14
    getScc  (0) 2024.09.14
    Fenwick2D  (0) 2024.09.01
    int128 setup  (0) 2024.08.31
    CompressedSparseRow  (0) 2024.08.27
Designed by Tistory.