結果
問題 | No.1326 ふたりのDominator |
ユーザー | Kude |
提出日時 | 2020-12-25 04:03:22 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 140 ms / 2,000 ms |
コード長 | 9,567 bytes |
コンパイル時間 | 2,810 ms |
コンパイル使用メモリ | 227,592 KB |
実行使用メモリ | 16,256 KB |
最終ジャッジ日時 | 2024-09-23 03:03:01 |
合計ジャッジ時間 | 5,616 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,944 KB |
testcase_04 | AC | 2 ms
6,940 KB |
testcase_05 | AC | 2 ms
6,940 KB |
testcase_06 | AC | 2 ms
6,940 KB |
testcase_07 | AC | 3 ms
6,940 KB |
testcase_08 | AC | 3 ms
6,940 KB |
testcase_09 | AC | 3 ms
6,940 KB |
testcase_10 | AC | 3 ms
6,940 KB |
testcase_11 | AC | 3 ms
6,940 KB |
testcase_12 | AC | 138 ms
9,984 KB |
testcase_13 | AC | 137 ms
9,984 KB |
testcase_14 | AC | 132 ms
9,984 KB |
testcase_15 | AC | 120 ms
9,984 KB |
testcase_16 | AC | 110 ms
10,240 KB |
testcase_17 | AC | 103 ms
11,776 KB |
testcase_18 | AC | 106 ms
13,952 KB |
testcase_19 | AC | 80 ms
15,616 KB |
testcase_20 | AC | 79 ms
14,464 KB |
testcase_21 | AC | 81 ms
14,464 KB |
testcase_22 | AC | 96 ms
16,256 KB |
testcase_23 | AC | 66 ms
9,724 KB |
testcase_24 | AC | 140 ms
9,984 KB |
コンパイルメッセージ
In member function 'void HLD::assign_idx(int, int, int&, int)', inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:200:23, inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:200:23, inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:200:23: main.cpp:197:19: warning: 'mi' may be used uninitialized [-Wmaybe-uninitialized] 197 | assign_idx(mi, h, nxt, u); | ~~~~~~~~~~^~~~~~~~~~~~~~~ main.cpp: In member function 'void HLD::assign_idx(int, int, int&, int)': main.cpp:189:13: note: 'mi' was declared here 189 | int mi; | ^~ In member function 'void HLD::assign_idx(int, int, int&, int)', inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:200:23, inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:200:23: main.cpp:197:19: warning: 'mi' may be used uninitialized [-Wmaybe-uninitialized] 197 | assign_idx(mi, h, nxt, u); | ~~~~~~~~~~^~~~~~~~~~~~~~~ main.cpp: In member function 'void HLD::assign_idx(int, int, int&, int)': main.cpp:189:13: note: 'mi' was declared here 189 | int mi; | ^~ In member function 'void HLD::assign_idx(int, int, int&, int)', inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:197:19, inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:200:23: main.cpp:197:19: warning: 'mi' may be used uninitialized [-Wmaybe-uninitialized] 197 | assign_idx(mi, h, nxt, u); | ~~~~~~~~~~^~~~~~~~~~~~~~~ main.cpp: In member function 'void HLD::assign_idx(int, int, int&, int)': main.cpp:189:13: note: 'mi' was declared here 189 | int mi; | ^~ In member function 'void HLD::assign_idx(int, int, int&, int)', inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:200:23, inlined from 'void HLD::assign_idx(int, int, int&, int)' at main.cpp:197:19: main.cpp:197:19:
ソースコード
#include<bits/stdc++.h> #include <cassert> #include <vector> #include <cassert> #include <numeric> #include <type_traits> namespace atcoder { namespace internal { #ifndef _MSC_VER template <class T> using is_signed_int128 = typename std::conditional<std::is_same<T, __int128_t>::value || std::is_same<T, __int128>::value, std::true_type, std::false_type>::type; template <class T> using is_unsigned_int128 = typename std::conditional<std::is_same<T, __uint128_t>::value || std::is_same<T, unsigned __int128>::value, std::true_type, std::false_type>::type; template <class T> using make_unsigned_int128 = typename std::conditional<std::is_same<T, __int128_t>::value, __uint128_t, unsigned __int128>; template <class T> using is_integral = typename std::conditional<std::is_integral<T>::value || is_signed_int128<T>::value || is_unsigned_int128<T>::value, std::true_type, std::false_type>::type; template <class T> using is_signed_int = typename std::conditional<(is_integral<T>::value && std::is_signed<T>::value) || is_signed_int128<T>::value, std::true_type, std::false_type>::type; template <class T> using is_unsigned_int = typename std::conditional<(is_integral<T>::value && std::is_unsigned<T>::value) || is_unsigned_int128<T>::value, std::true_type, std::false_type>::type; template <class T> using to_unsigned = typename std::conditional< is_signed_int128<T>::value, make_unsigned_int128<T>, typename std::conditional<std::is_signed<T>::value, std::make_unsigned<T>, std::common_type<T>>::type>::type; #else template <class T> using is_integral = typename std::is_integral<T>; template <class T> using is_signed_int = typename std::conditional<is_integral<T>::value && std::is_signed<T>::value, std::true_type, std::false_type>::type; template <class T> using is_unsigned_int = typename std::conditional<is_integral<T>::value && std::is_unsigned<T>::value, std::true_type, std::false_type>::type; template <class T> using to_unsigned = typename std::conditional<is_signed_int<T>::value, std::make_unsigned<T>, std::common_type<T>>::type; #endif template <class T> using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>; template <class T> using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>; template <class T> using to_unsigned_t = typename to_unsigned<T>::type; } // namespace internal } // namespace atcoder namespace atcoder { template <class T> struct fenwick_tree { using U = internal::to_unsigned_t<T>; public: fenwick_tree() : _n(0) {} fenwick_tree(int n) : _n(n), data(n) {} void add(int p, T x) { assert(0 <= p && p < _n); p++; while (p <= _n) { data[p - 1] += U(x); p += p & -p; } } T sum(int l, int r) { assert(0 <= l && l <= r && r <= _n); return sum(r) - sum(l); } private: int _n; std::vector<U> data; U sum(int r) { U s = 0; while (r > 0) { s += data[r - 1]; r -= r & -r; } return s; } }; } // namespace atcoder using namespace std; using namespace atcoder; #define rep(i,n) for(int i = 0; i < (n); ++i) #define rrep(i,n) for(int i = (n)-1; i >= 0; --i) #define chmax(a, b) a = max(a, b) #define chmin(a, b) a = min(a, b) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() using ll = long long; using P = pair<int,int>; using VI = vector<int>; using VVI = vector<VI>; using VL = vector<ll>; using VVL = vector<VL>; struct HLD { std::vector<std::vector<int>> &to; int root, n; std::vector<int> sz, parent, depth, idx, ridx, head, inv; HLD(std::vector<std::vector<int>>& to, int root=0): to(to), root(root), n(to.size()), sz(n), parent(n), depth(n), idx(n), ridx(n), head(n), inv(n) { init_tree_data(root); int x = 0; assign_idx(root, root, x); } void init_tree_data(int u, int p=-1, int d=0) { parent[u] = p; depth[u] = d; int s = 1; for(int v: to[u]) { if (v == p) continue; init_tree_data(v, u, d+1); s += sz[v]; } sz[u] = s; } void assign_idx(int u, int h, int &nxt, int p=-1) { head[u] = h; inv[nxt] = u; idx[u] = nxt++; if (sz[u] == 1) { ridx[u] = nxt; return; } int mxsize = 0; int mi; for(int v: to[u]) { if (v == p) continue; if (sz[v] > mxsize) { mxsize = sz[v]; mi = v; } } assign_idx(mi, h, nxt, u); for(int v: to[u]) { if (v == p || v == mi) continue; assign_idx(v, v, nxt, u); } ridx[u] = nxt; } int lca(int u, int v) { while(head[u] != head[v]) { if (depth[head[u]] > depth[head[v]]) u = parent[head[u]]; else v = parent[head[v]]; } return (depth[u] < depth[v] ? u : v); } // returns (paths upto lca from x (excluding lca), those from y, lca) std::tuple<std::vector<std::pair<int, int>>, std::vector<std::pair<int, int>>, int> paths(int x, int y) { std::tuple<std::vector<std::pair<int, int>>, std::vector<std::pair<int, int>>, int> ret; std::vector<std::pair<int, int>>& x_paths = get<0>(ret); std::vector<std::pair<int, int>>& y_paths = get<1>(ret); int& lca = get<2>(ret); while(head[x] != head[y]) { int xhead = head[x], yhead = head[y]; if (depth[xhead] > depth[yhead]) { x_paths.emplace_back(x, xhead); x = parent[xhead]; } else { y_paths.emplace_back(y, yhead); y = parent[yhead]; } } if (depth[x] > depth[y]) { int ychild = inv[idx[y] + 1]; x_paths.emplace_back(x, ychild); x = y; } else if (depth[x] < depth[y]) { int xchild = inv[idx[x] + 1]; y_paths.emplace_back(y, xchild); y = x; } lca = x; return ret; } }; std::tuple< std::vector<std::vector<int>>, std::vector<int>, std::vector<int>> lowlink(std::vector<std::vector<int>>& to, int root=0) { // returns a tuple of (spanning_tree (directed), ord, low) std::tuple< std::vector<std::vector<int>>, std::vector<int>, std::vector<int>> res; int n = to.size(); auto& tree = std::get<0>(res); auto& ord = std::get<1>(res); auto& low = std::get<2>(res); tree.resize(n); ord.resize(n, -1); low.resize(n); int nxt_ord = 0; auto dfs = [&](auto&& self, int u, int parent=-1)->void { low[u] = ord[u] = nxt_ord++; for(int v: to[u]) { if (v == parent) continue; if (ord[v] == -1) { tree[u].push_back(v); self(self, v, u); if (low[v] < low[u]) low[u] = low[v]; } else { if (ord[v] < low[u]) low[u] = ord[v]; } } }; dfs(dfs, root); return res; } int main() { ios::sync_with_stdio(false); cin.tie(0); int n, m; cin >> n >> m; VVI graph(n); rep(i, m) { int u, v; cin >> u >> v; --u, --v; graph[u].push_back(v); graph[v].push_back(u); } auto [tree, ord, low] = lowlink(graph); HLD d(tree); fenwick_tree<int> fw(n); for(int i = 1; i < n; i++) { int p = d.parent[i]; if (p == 0 && tree[p].size() >= 2 || p != 0 && low[i] >= ord[p]) fw.add(d.idx[i], 1); } int q; cin >> q; while(q--) { int x, y; cin >> x >> y; x--, y--; if (x == y) { cout << 0 << '\n'; continue; } if (d.depth[x] > d.depth[y]) swap(x, y); auto [xpaths, ypaths, lca] = d.paths(x, y); int ans = 0; bool x_added = false, y_added = false; for(auto [s, t]: xpaths) { int si = d.idx[s], ti = d.idx[t]; ans += fw.sum(ti, si + 1); x_added = fw.sum(ti, ti + 1) == 1; } for(auto [s, t]: ypaths) { int si = d.idx[s], ti = d.idx[t]; ans += fw.sum(ti, si + 1); y_added = fw.sum(ti, ti + 1) == 1; } if ((x == lca || x_added) && y_added) ans -= 1; cout << ans << '\n'; } }