結果
問題 | No.2981 Pack Tree into Grid |
ユーザー | KumaTachiRen |
提出日時 | 2024-11-29 21:36:57 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 20 ms / 2,000 ms |
コード長 | 6,096 bytes |
コンパイル時間 | 4,476 ms |
コンパイル使用メモリ | 284,912 KB |
実行使用メモリ | 6,820 KB |
最終ジャッジ日時 | 2024-12-04 23:31:41 |
合計ジャッジ時間 | 6,974 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,820 KB |
testcase_01 | AC | 11 ms
6,820 KB |
testcase_02 | AC | 10 ms
6,816 KB |
testcase_03 | AC | 10 ms
6,820 KB |
testcase_04 | AC | 10 ms
6,820 KB |
testcase_05 | AC | 12 ms
6,820 KB |
testcase_06 | AC | 18 ms
6,816 KB |
testcase_07 | AC | 19 ms
6,820 KB |
testcase_08 | AC | 19 ms
6,816 KB |
testcase_09 | AC | 20 ms
6,820 KB |
testcase_10 | AC | 9 ms
6,820 KB |
testcase_11 | AC | 9 ms
6,820 KB |
testcase_12 | AC | 9 ms
6,816 KB |
testcase_13 | AC | 9 ms
6,816 KB |
testcase_14 | AC | 10 ms
6,816 KB |
testcase_15 | AC | 9 ms
6,816 KB |
testcase_16 | AC | 9 ms
6,816 KB |
testcase_17 | AC | 9 ms
6,820 KB |
testcase_18 | AC | 9 ms
6,816 KB |
testcase_19 | AC | 9 ms
6,820 KB |
testcase_20 | AC | 9 ms
6,816 KB |
testcase_21 | AC | 5 ms
6,820 KB |
testcase_22 | AC | 4 ms
6,816 KB |
testcase_23 | AC | 5 ms
6,816 KB |
testcase_24 | AC | 7 ms
6,820 KB |
testcase_25 | AC | 5 ms
6,820 KB |
testcase_26 | AC | 5 ms
6,816 KB |
testcase_27 | AC | 3 ms
6,820 KB |
testcase_28 | AC | 16 ms
6,820 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; #include <atcoder/modint> struct Fast { Fast() { std::cin.tie(nullptr); ios::sync_with_stdio(false); cout << setprecision(10); } } fast; #define all(a) (a).begin(), (a).end() #define contains(a, x) ((a).find(x) != (a).end()) #define rep(i, a, b) for (int i = (a); i < (int)(b); i++) using ll = long long; struct RandomNumberGenerator { mt19937 mt; RandomNumberGenerator() : mt(chrono::steady_clock::now().time_since_epoch().count()) {} int operator()(int n) { uniform_int_distribution<int> dist(0, n - 1); return dist(mt); } }; void calc_distance(const vector<vector<int>> &g, const int root, vector<int> &dist, vector<int> &prev, int &last_vertex) { queue<int> qu; qu.push(root); dist[root] = 0; prev[root] = -1; while (!qu.empty()) { auto x = qu.front(); qu.pop(); last_vertex = x; for (auto y : g[x]) if (prev[x] != y) { qu.push(y); dist[y] = dist[x] + 1; prev[y] = x; } } } pair<int, int> find_center(const vector<vector<int>> &g) { int u, v; vector<int> dist(g.size(), 0), prev(g.size(), -1); calc_distance(g, 0, dist, prev, u); calc_distance(g, u, dist, prev, v); int d = dist[v] / 2, x = v; rep(i, 0, d) x = prev[x]; return {x, (dist[v] & 1) ? prev[x] : -1}; } bool solve_rooted(const int N, const vector<vector<int>> &T1, const vector<vector<int>> &T2, const vector<pair<int, int>> &T2_pos, const int T1_root, const int T2_root) { if (T1_root == -1 || T2_root == -1) return false; RandomNumberGenerator rnd; using mint = atcoder::modint998244353; vector<vector<mint>> T1_hash, T2_hash; rep(k, 0, 2) { vector<int> depth_val; auto dfs = [&](auto self, int x, int p, const vector<vector<int>> &T, vector<mint> &hash) -> int { int d = 0; mint prod = 1; for (auto y : T[x]) { if (y == p) continue; d = max(d, self(self, y, x, T, hash) + 1); prod *= hash[y]; } while (depth_val.size() <= d) depth_val.push_back(rnd(mint::mod())); hash[x] = depth_val[d] + prod; return d; }; vector<mint> T1_hash_tmp(T1.size()), T2_hash_tmp(T2.size()); dfs(dfs, T1_root, -1, T1, T1_hash_tmp); dfs(dfs, T2_root, -1, T2, T2_hash_tmp); if (T1_hash_tmp[T1_root] != T2_hash_tmp[T2_root]) return false; T1_hash.push_back(T1_hash_tmp); T2_hash.push_back(T2_hash_tmp); } vector<pair<int, int>> ans(N, {-1, -1}); auto dfs2 = [&](auto self, int x1, int p1, int x2, int p2) -> void { if (x1 < N) ans[x1] = T2_pos[x2]; vector<pair<int, int>> children1, children2; for (auto y : T1[x1]) if (y != p1) children1.push_back({(uint64_t(T1_hash[0][y].val()) << 32) + T1_hash[1][y].val(), y}); for (auto y : T2[x2]) if (y != p2) children2.push_back({(uint64_t(T2_hash[0][y].val()) << 32) + T2_hash[1][y].val(), y}); sort(all(children1)); sort(all(children2)); rep(i, 0, children1.size()) self(self, children1[i].second, x1, children2[i].second, x2); }; dfs2(dfs2, T1_root, -1, T2_root, -1); cout << "Yes" << "\n"; rep(i, 0, N) { auto [x, y] = ans[i]; cout << (x + 1) << " " << (y + 1) << "\n"; } return true; } void solve() { int N, H, W; cin >> N; vector<tuple<int, int, int>> T; rep(i, 0, N - 1) { int u, v, w; cin >> u >> v >> w; T.push_back({u, v, w}); } cin >> H >> W; vector<string> S(H); rep(i, 0, H) cin >> S[i]; size_t T1_size = 1, T2_size = 0; for (auto [u, v, w] : T) T1_size += w; rep(i, 0, H) rep(j, 0, W) T2_size += S[i][j] == '#'; if (T1_size != T2_size) { cout << "No" << "\n"; return; } vector<vector<int>> T1(T1_size, vector<int>()), T2(T2_size, vector<int>()); vector<pair<int, int>> T2_pos; { size_t dummy = N; for (auto [u, v, w] : T) { u--, v--; if (w == 1) { T1[u].push_back(v), T1[v].push_back(u); } else { T1[u].push_back(dummy), T1[dummy].push_back(u); rep(i, 0, w - 2) { T1[dummy].push_back(dummy + 1), T1[dummy + 1].push_back(dummy); dummy++; } T1[v].push_back(dummy), T1[dummy].push_back(v); dummy++; } } } { vector<vector<int>> T2_index(H, vector<int>(W, -1)); rep(i, 0, H) rep(j, 0, W) if (S[i][j] == '#') T2_index[i][j] = T2_pos.size(), T2_pos.push_back({i, j}); rep(i, 0, T2.size()) { auto [x1, y1] = T2_pos[i]; rep(k, 0, 4) { int x2 = x1 + (k & 1 ? 0 : 1 - k); int y2 = y1 + (k & 1 ? 2 - k : 0); if (x2 < 0 || x2 >= H || y2 < 0 || y2 >= W) continue; if (T2_index[x2][y2] != -1) T2[i].push_back(T2_index[x2][y2]); } } } size_t T1_deg_max = 0, T2_deg_max = 0; rep(i, 0, T1_size) T1_deg_max = max(T1_deg_max, T1[i].size()); rep(i, 0, T2_size) T2_deg_max = max(T2_deg_max, T2[i].size()); if (T1_deg_max != T2_deg_max) { cout << "No" << "\n"; return; } auto [T1_c1, T1_c2] = find_center(T1); auto [T2_c1, T2_c2] = find_center(T2); if (solve_rooted(N, T1, T2, T2_pos, T1_c1, T2_c1)) return; if (solve_rooted(N, T1, T2, T2_pos, T1_c1, T2_c2)) return; if (solve_rooted(N, T1, T2, T2_pos, T1_c2, T2_c1)) return; if (solve_rooted(N, T1, T2, T2_pos, T1_c2, T2_c2)) return; cout << "No" << "\n"; } int main() { int t = 1; cin >> t; while (t--) solve(); }