Submission #1251659

#TimeUsernameProblemLanguageResultExecution timeMemory
1251659jwvg0425세계 지도 (IOI25_worldmap)C++20
72 / 100
46 ms5448 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 s) : color(c), sz(s), depth(0), coverC(0) {}

	int color;
	int sz;
	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 + sz; i++)
			for (int j = y; j < y + sz; 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;
		sz += 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->sz;
			int ly = cp.yy - 1;
			int ry = cp.yy + v->sz;

			if (p.xx >= lx && p.xx <= rx && p.yy >= ly && p.yy <= ry)
				return true;
		}

		return false;
	}

	vector<ii> getCells()
	{
		vector<ii> res;

		for (int y = sz - 2; y >= 0; y-= 2)
		{
			for (int x = y % 2; x < sz - 1; x += 2)
			{
				if (isAdj(ii(x, y)))
					continue;

				res.emplace_back(x, y);
			}
		}

		return res;
	}
};

void arrange(vector<RectBoard*>& childs)
{
	int minCoverC = 0;
	int idx = 0;

	for (int i = 0; i < childs.size(); i++)
	{
		if (childs[i]->coverC > minCoverC)
		{
			minCoverC = childs[i]->coverC;
			idx = i;
		}
	}

	swap(childs[0], childs[idx]);
}

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<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
		{
			childBoards.push_back(dfs(c, maxFirst));
			maxFirst = false;
		}
	}

	// leaf node
	if (childBoards.empty())
		return new RectBoard(root, 1);

	for (int i = 1; i < childBoards.size(); i++)
	{
		// 왼쪽 위 감싸기
		childBoards[i]->cover();
	}

	// 자식을 한 칸씩 띄고 배치할 수 있을 만큼으로 크기 지정
	int sz = childBoards.size();
	for (auto& c : childBoards)
		sz += c->sz;

	auto res = new RectBoard(root, sz);
	int x = 0, y = 0;

	for (auto& c : childBoards)
	{
		res->add_child(x, y, c);
		x += c->sz + 1;
	}

	// back edge 칸 계산
	while (true)
	{
		vector<ii> cells = res->getCells();

		if (cells.size() < backEdges.size())
		{
			res->sz += 2;
			continue;
		}

		for (int i =0;i < backEdges.size(); i++)
			res->add_child(cells[i].xx, cells[i].yy, new RectBoard(backEdges[i], 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);

	vector<vector<int>> ans(res->sz, vector<int>(res->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...