Submission #1252490

#TimeUsernameProblemLanguageResultExecution timeMemory
1252490jwvg0425World Map (IOI25_worldmap)C++20
93 / 100
37 ms2376 KiB
#include "worldmap.h" #include <stdio.h> #include <vector> #include <queue> #include <algorithm> #include <iostream> #include <string> #include <bitset> #include <map> #include <set> #include <tuple> #include <string.h> #include <math.h> #include <random> #include <functional> #include <assert.h> #define all(x) (x).begin(), (x).end() #define xx first #define yy second using namespace std; template<typename T, typename Pr = less<T>> using pq = priority_queue<T, vector<T>, Pr>; using i64 = long long int; using ii = pair<int, int>; using ii64 = pair<i64, i64>; vector<int> edges[45]; int d[45], h[45]; struct RectBoard { RectBoard(int c, int a, int b) : color(c), width(a), height(b), depth(0), coverC(0) {} int color; int width, height; int depth; int coverC = 0; ~RectBoard() { for (auto& [k, p] : childs) delete p; } void add_child(int x, int y, RectBoard* r) { childs.emplace_back(ii(x, y), r); depth = max(depth, r->depth + 1); if (childs.size() == 1) coverC = childs[0].yy->coverC + 1; } vector<pair<ii, RectBoard*>> childs; void paint(vector<vector<int>>& res, int x, int y) { for (int i = x; i < x + width; i++) for (int j = y; j < y + height; j++) res[i][j] = color; for (auto& [p, c] : childs) c->paint(res, x + p.xx, y + p.yy); } int cover() { // cover 필요 없는 경우 if (childs.empty()) return 0; if (childs[0].xx.xx != 0 && childs[0].xx.yy != 0) return 0; auto csz = childs[0].yy->cover() + 1; childs[0].xx.xx += 1; childs[0].xx.yy += 1; width += csz; height += csz; for (int i = 1; i < childs.size(); i++) { childs[i].xx.xx += csz; childs[i].xx.yy += csz; } return csz; } bool isAdj(ii p) { for (auto& [cp, v] : childs) { int lx = cp.xx - 1; int rx = cp.xx + v->width; int ly = cp.yy - 1; int ry = cp.yy + v->height; if (p.xx == lx && p.yy == ly) continue; if (p.xx == lx && p.yy == ry) continue; if (p.xx == rx && p.yy == ly) continue; if (p.xx == rx && p.yy == ry) continue; if (p.xx >= lx && p.xx <= rx && p.yy >= ly && p.yy <= ry) return true; } return false; } vector<ii> getCells() { vector<ii> res1; for (int y = 0; y < height - 1; y++) { for (int x = y % 2; x < width - 1; x += 2) { if (isAdj(ii(x, y))) continue; res1.emplace_back(x, y); } } vector<ii> res2; for (int y = 0; y < height - 1; y ++) { for (int x = (y + 1) % 2; x < width - 1; x += 2) { if (isAdj(ii(x, y))) continue; res2.emplace_back(x, y); } } if (res1.size() > res2.size()) return res1; else return res2; } void transpose() { swap(width, height); for (auto& [p, c] : childs) { swap(p.xx, p.yy); c->transpose(); } } }; void predfs(int root) { for (auto& c : edges[root]) { if (d[c] != -1) continue; d[c] = d[root] + 1; predfs(c); h[root] = max(h[root], h[c] + 1); } } RectBoard* dfs(int root, bool maxFirst) { vector<int> backEdges; vector<pair<ii, RectBoard*>> childBoards; if (maxFirst) sort(all(edges[root]), [](int l, int r) { return h[r] < h[l]; }); else sort(all(edges[root]), [](int l, int r) { return h[l] < h[r]; }); for (auto& c : edges[root]) { if (d[c] < d[root]) continue; // back edge 여부 체크 if (d[c] != d[root] + 1) backEdges.push_back(c); else { auto dfsr = dfs(c, maxFirst); if (dfsr->width == 1 && dfsr->height == 1) { backEdges.push_back(dfsr->color); delete dfsr; } else { childBoards.emplace_back(ii(0, 0), dfsr); } maxFirst = false; } } // leaf node if (childBoards.empty() && backEdges.empty()) return new RectBoard(root, 1, 1); for (int i = 1; i < childBoards.size(); i++) { // 왼쪽 위 감싸기 childBoards[i].yy->cover(); } // 자식을 한 칸씩 띄고 배치할 수 있을 만큼으로 크기 지정 int width = 0; int height = 0; for (auto& [p, c] : childBoards) { // width를 확장할지 height를 확장할지 정하기 if (width < height) { if (c->width > c->height) c->transpose(); p.xx = width; p.yy = 0; width += c->width + 1; height = max(height, c->height + 1); } else { if (c->height > c->width) c->transpose(); p.xx = 0; p.yy = height; height += c->height + 1; width = max(width, c->width + 1); } } auto res = new RectBoard(root, width, height); for (auto& [p, c] : childBoards) { if (c == nullptr) continue; res->add_child(p.xx, p.yy, c); } // back edge 칸 계산 while (true) { vector<ii> cells = res->getCells(); if (cells.size() < backEdges.size()) { if (res->width < res->height) res->width += 2; else res->height += 2; continue; } for (int i = 0;i < backEdges.size(); i++) res->add_child(cells[i].xx, cells[i].yy, new RectBoard(backEdges[i], 1, 1)); break; } return res; } vector<vector<int>> create_map(int N, int M, vector<int> A, vector<int> B) { for (int i = 1; i <= N; i++) edges[i].clear(); memset(d, -1, sizeof(d)); memset(h, 0, sizeof(h)); for (int i = 0; i < M; i++) { edges[A[i]].push_back(B[i]); edges[B[i]].push_back(A[i]); } d[1] = 0; predfs(1); auto res = dfs(1, true); auto sz = max(res->width, res->height); res->width = sz; res->height = sz; vector<vector<int>> ans(sz, vector<int>(sz)); res->paint(ans, 0, 0); delete res; return ans; }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...