結果
問題 | No.2981 Pack Tree into Grid |
ユーザー | 👑 rin204 |
提出日時 | 2024-12-05 01:00:54 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 290 ms / 2,000 ms |
コード長 | 9,047 bytes |
コンパイル時間 | 3,790 ms |
コンパイル使用メモリ | 282,128 KB |
実行使用メモリ | 11,188 KB |
最終ジャッジ日時 | 2024-12-05 01:01:01 |
合計ジャッジ時間 | 6,685 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 19 ms
5,248 KB |
testcase_02 | AC | 20 ms
5,248 KB |
testcase_03 | AC | 21 ms
5,248 KB |
testcase_04 | AC | 21 ms
5,248 KB |
testcase_05 | AC | 29 ms
5,248 KB |
testcase_06 | AC | 52 ms
5,248 KB |
testcase_07 | AC | 54 ms
5,248 KB |
testcase_08 | AC | 55 ms
5,248 KB |
testcase_09 | AC | 62 ms
5,248 KB |
testcase_10 | AC | 17 ms
5,248 KB |
testcase_11 | AC | 18 ms
5,248 KB |
testcase_12 | AC | 18 ms
5,248 KB |
testcase_13 | AC | 21 ms
5,248 KB |
testcase_14 | AC | 23 ms
5,248 KB |
testcase_15 | AC | 14 ms
5,248 KB |
testcase_16 | AC | 13 ms
5,248 KB |
testcase_17 | AC | 14 ms
5,248 KB |
testcase_18 | AC | 15 ms
5,248 KB |
testcase_19 | AC | 14 ms
5,248 KB |
testcase_20 | AC | 15 ms
5,248 KB |
testcase_21 | AC | 163 ms
9,556 KB |
testcase_22 | AC | 290 ms
11,188 KB |
testcase_23 | AC | 10 ms
5,248 KB |
testcase_24 | AC | 13 ms
5,248 KB |
testcase_25 | AC | 9 ms
5,248 KB |
testcase_26 | AC | 9 ms
5,248 KB |
testcase_27 | AC | 6 ms
5,248 KB |
testcase_28 | AC | 56 ms
5,248 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; struct RandomNumberGenerator { std::mt19937 mt; RandomNumberGenerator() : mt(std::chrono::steady_clock::now().time_since_epoch().count()) {} RandomNumberGenerator(int seed) : mt(seed) {} int operator()(int a, int b) { std::uniform_int_distribution<int> dist(a, b - 1); return dist(mt); } int operator()(int b) { return (*this)(0, b); } template <typename T> void shuffle(std::vector<T> &v) { std::shuffle(v.begin(), v.end(), mt); } }; std::vector<long long> treeHash(std::vector<std::vector<int>> &edges, int root = 0, const long long MOD = 998244353, int seed = 0) { int n = edges.size(); std::vector<int> dist(n, -1); std::vector<int> route; std::stack<int> st; st.push(root); route.push_back(root); dist[root] = 0; while (!st.empty()) { int pos = st.top(); st.pop(); for (auto npos : edges[pos]) { if (dist[npos] == -1) { dist[npos] = dist[pos] + 1; st.push(npos); route.push_back(npos); } } } std::reverse(route.begin(), route.end()); int d = 0; for (auto di : dist) d = std::max(d, di); std::vector<long long> X(d + 1); RandomNumberGenerator rng(seed); for (int i = 0; i <= d; i++) X[i] = rng(MOD); std::vector<int> ma(n, 0); std::vector<long long> hash(n, 1); for (auto pos : route) { for (auto npos : edges[pos]) { if (dist[npos] < dist[pos]) continue; ma[pos] = std::max(ma[pos], ma[npos] + 1); } auto x = X[ma[pos]]; for (auto npos : edges[pos]) { if (dist[npos] < dist[pos]) continue; hash[pos] *= (x + hash[npos]); hash[pos] %= MOD; } } return hash; } std::vector<int> treeIsomorphism(std::vector<std::vector<int>> &edges1, std::vector<std::vector<int>> &edges2) { auto get_centroids = [&](std::vector<std::vector<int>> &edges) { int n = edges.size(); std::vector<int> centroids; std::vector<int> sz(n); std::function<void(int, int)> dfs = [&](int pos, int par) { sz[pos] = 1; bool is_centroid = true; for (auto npos : edges[pos]) { if (npos == par) continue; dfs(npos, pos); sz[pos] += sz[npos]; if (sz[npos] > n / 2) is_centroid = false; } if (n - sz[pos] > n / 2) is_centroid = false; if (is_centroid) centroids.push_back(pos); }; dfs(0, -1); return centroids; }; auto cent1 = get_centroids(edges1); auto cent2 = get_centroids(edges2); RandomNumberGenerator rng; int seed1 = rng(1 << 30); int seed2 = rng(1 << 30); auto get_hash = [&](std::vector<std::vector<int>> &edges, int centroid) { const int MOD9 = 998244353; const int MOD1 = 1000000007; auto h1 = treeHash(edges, centroid, MOD9, seed1); auto h2 = treeHash(edges, centroid, MOD1, seed2); std::vector<long long> hash(h1.size()); for (size_t i = 0; i < h1.size(); i++) { hash[i] = ((long long)(h1[i]) << 32) | h2[i]; } return hash; }; for (auto c1 : cent1) { auto h1 = get_hash(edges1, c1); for (auto c2 : cent2) { auto h2 = get_hash(edges2, c2); if (h1[c1] == h2[c2]) { std::vector<int> P(edges1.size(), -1); std::function<void(int, int, int, int)> dfs = [&](int pos1, int bpos1, int pos2, int bpos2) { P[pos1] = pos2; std::map<long long, std::vector<int>> mp; for (auto npos2 : edges2[pos2]) { if (npos2 == bpos2) continue; mp[h2[npos2]].push_back(npos2); } for (auto npos1 : edges1[pos1]) { if (npos1 == bpos1) continue; int npos2 = mp[h1[npos1]].back(); mp[h1[npos1]].pop_back(); dfs(npos1, pos1, npos2, pos2); } }; dfs(c1, -1, c2, -1); return P; } } } return {}; } void solve() { int n; cin >> n; int nex = n; vector<vector<int>> edges(n); for (int i = 0; i < n - 1; i++) { int u, v, w; cin >> u >> v >> w; u--; v--; for (int j = 0; j < w - 1; j++) { edges.push_back({}); edges[u].push_back(nex); edges[nex].push_back(u); u = nex; nex++; } edges[u].push_back(v); edges[v].push_back(u); } int h, w; cin >> h >> w; vector<vector<char>> S(h, vector<char>(w)); for (auto &row : S) { for (auto &c : row) { cin >> c; } } vector<vector<int>> idx(h, vector<int>(w, -1)); int n2 = 0; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { if (S[i][j] == '#') { idx[i][j] = n2++; } } } if (n2 != edges.size()) { cout << "No" << endl; return; } vector<vector<int>> edges2(n2); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { if (S[i][j] != '#') continue; if (i > 0 and S[i - 1][j] == '#') { edges2[idx[i][j]].push_back(idx[i - 1][j]); edges2[idx[i - 1][j]].push_back(idx[i][j]); } if (j > 0 and S[i][j - 1] == '#') { edges2[idx[i][j]].push_back(idx[i][j - 1]); edges2[idx[i][j - 1]].push_back(idx[i][j]); } } } auto P = treeIsomorphism(edges, edges2); if (P.empty()) { cout << "No" << endl; return; } cout << "Yes" << endl; vector<pair<int, int>> to(n2); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { if (idx[i][j] != -1) { to[idx[i][j]] = {i + 1, j + 1}; } } } for (int i = 0; i < n; i++) { int p = P[i]; cout << to[p].first << " " << to[p].second << endl; } } int main() { int t; std::cin >> t; while (t--) solve(); return 0; } // #include <bits/stdc++.h> // using namespace std; // // #include "tree/treeIsomorphism.hpp" // // void solve() { // int n; // cin >> n; // int nex = n; // vector<vector<int>> edges(n); // for (int i = 0; i < n - 1; i++) { // int u, v, w; // cin >> u >> v >> w; // u--; // v--; // for (int j = 0; j < w - 1; j++) { // edges.push_back({}); // edges[u].push_back(nex); // edges[nex].push_back(u); // u = nex; // nex++; // } // edges[u].push_back(v); // edges[v].push_back(u); // } // // int h, w; // cin >> h >> w; // vector<vector<char>> S(h, vector<char>(w)); // for (auto &row : S) { // for (auto &c : row) { // cin >> c; // } // } // vector<vector<int>> idx(h, vector<int>(w, -1)); // int n2 = 0; // for (int i = 0; i < h; i++) { // for (int j = 0; j < w; j++) { // if (S[i][j] == '#') { // idx[i][j] = n2++; // } // } // } // // if (n2 != edges.size()) { // cout << "No" << endl; // return; // } // // vector<vector<int>> edges2(n2); // for (int i = 0; i < h; i++) { // for (int j = 0; j < w; j++) { // if (S[i][j] != '#') continue; // if (i > 0 and S[i - 1][j] == '#') { // edges2[idx[i][j]].push_back(idx[i - 1][j]); // edges2[idx[i - 1][j]].push_back(idx[i][j]); // } // if (j > 0 and S[i][j - 1] == '#') { // edges2[idx[i][j]].push_back(idx[i][j - 1]); // edges2[idx[i][j - 1]].push_back(idx[i][j]); // } // } // } // // auto P = treeIsomorphism(edges, edges2); // // if (P.empty()) { // cout << "No" << endl; // return; // } // // cout << "Yes" << endl; // // vector<pair<int, int>> to(n2); // // for (int i = 0; i < h; i++) { // for (int j = 0; j < w; j++) { // if (idx[i][j] != -1) { // to[idx[i][j]] = {i + 1, j + 1}; // } // } // } // // for (int i = 0; i < n; i++) { // int p = P[i]; // cout << to[p].first << " " << to[p].second << endl; // } // } // // int main() { // int t; // std::cin >> t; // while (t--) solve(); // return 0; // }