Submission #378080

#TimeUsernameProblemLanguageResultExecution timeMemory
378080smaxOne-Way Streets (CEOI17_oneway)C++17
100 / 100
180 ms50648 KiB
#include <bits/stdc++.h> using namespace std; #ifdef LOCAL #define DEBUG(...) debug(#__VA_ARGS__, __VA_ARGS__) #else #define DEBUG(...) 6 #endif template<typename T, typename S> ostream& operator << (ostream &os, const pair<T, S> &p) {return os << "(" << p.first << ", " << p.second << ")";} template<typename C, typename T = decay<decltype(*begin(declval<C>()))>, typename enable_if<!is_same<C, string>::value>::type* = nullptr> ostream& operator << (ostream &os, const C &c) {bool f = true; os << "["; for (const auto &x : c) {if (!f) os << ", "; f = false; os << x;} return os << "]";} template<typename T> void debug(string s, T x) {cerr << s << " = " << x << "\n";} template <typename T, typename... Args> void debug(string s, T x, Args... args) {for (int i=0, b=0; i<(int)s.size(); i++) if (s[i] == '(' || s[i] == '{') b++; else if (s[i] == ')' || s[i] == '}') b--; else if (s[i] == ',' && b == 0) {cerr << s.substr(0, i) << " = " << x << " | "; debug(s.substr(s.find_first_not_of(' ', i + 1)), args...); break;}} struct BridgeTree { int n, eid, ti; vector<int> num, id, stk; vector<vector<int>> comp; vector<pair<int, int>> edges; vector<vector<pair<int, int>>> adj, tree; BridgeTree(int _n) : n(_n), eid(0), ti(0), num(n), id(n), adj(n) {} void addEdge(int u, int v) { adj[u].emplace_back(v, eid); adj[v].emplace_back(u, eid); edges.emplace_back(u, v); eid++; } void init() { for (int u=0; u<n; u++) if (!num[u]) { dfs(u, -1); comp.emplace_back(); while (!stk.empty()) { id[stk.back()] = (int) comp.size() - 1; comp.back().push_back(stk.back()); stk.pop_back(); } } tree.resize(comp.size()); for (auto &c : comp) for (int u : c) for (auto [v, i] : adj[u]) if (id[u] != id[v]) tree[id[u]].emplace_back(id[v], i); } int dfs(int u, int p) { int low = num[u] = ++ti; stk.push_back(u); for (auto [v, i] : adj[u]) if (i != p) { if (!num[v]) { int ret = dfs(v, i); low = min(low, ret); if (num[u] < ret) { comp.emplace_back(); while (comp.back().empty() || comp.back().back() != v) { id[stk.back()] = (int) comp.size() - 1; comp.back().push_back(stk.back()); stk.pop_back(); } } } else { low = min(low, num[v]); } } return low; } }; template<typename T> struct RMQ { vector<vector<T>> spt; RMQ(const vector<T> &a) : spt(1, a) { int n = (int) a.size(); for (int j=1; 1<<j<=n; j++) { spt.emplace_back(n - (1 << j) + 1); for (int i=0; i+(1<<j)<=n; i++) spt[j][i] = min(spt[j-1][i], spt[j-1][i+(1<<(j-1))]); } } T query(int i, int j) { int k = __lg(j - i + 1); return min(spt[k][i], spt[k][j-(1<<k)+1]); } }; struct LCA { int n, cid; vector<int> pos, depth, comp, path, ret, par; vector<vector<pair<int, int>>> adj; RMQ<int> rmq; LCA(int _n) : n(_n), cid(0), pos(n), depth(n), comp(n), adj(n), rmq({}) {} LCA(const vector<vector<pair<int, int>>> &_adj) : n((int) _adj.size()), cid(0), pos(n), depth(n), comp(n), par(n), adj(_adj), rmq({}) {} // void addEdge(int u, int v) { // adj[u].push_back(v); // adj[v].push_back(u); // } void init() { for (int u=0; u<n; u++) if (!comp[u]) { cid++; dfs(u, -1); } rmq = RMQ<int>(ret); } void dfs(int u, int p) { pos[u] = (int) path.size(); comp[u] = cid; path.push_back(u); ret.push_back(pos[u]); for (auto [v, i] : adj[u]) if (v != p) { depth[v] = depth[u] + 1; par[v] = i; dfs(v, u); path.push_back(u); ret.push_back(pos[u]); } } int lca(int u, int v) { if (pos[u] > pos[v]) swap(u, v); return path[rmq.query(pos[u], pos[v])]; } int dist(int u, int v) { return depth[u] + depth[v] - 2 * depth[lca(u, v)]; } bool same(int u, int v) { return comp[u] == comp[v]; } }; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int n, m; cin >> n >> m; BridgeTree bt(n); for (int i=0; i<m; i++) { int u, v; cin >> u >> v; u--, v--; bt.addEdge(u, v); } bt.init(); LCA lca(bt.tree); lca.init(); int o = (int) bt.tree.size(); vector<pair<int, int>> dir(o, {o, -1}); int q; cin >> q; for (int i=0; i<q; i++) { int s, d; cin >> s >> d; s--, d--; s = bt.id[s], d = bt.id[d]; if (!lca.same(s, d)) assert(false); int w = lca.lca(s, d); if (s != w) { if (dir[s].second != -1 && dir[s].second != 0) assert(false); dir[s] = min(dir[s], {lca.depth[w], 0}); } if (d != w) { if (dir[d].second != -1 && dir[d].second != 1) assert(false); dir[d] = min(dir[d], {lca.depth[w], 1}); } } vector<bool> vis(o); auto dfs = [&] (auto &self, int u, int p) -> void { vis[u] = true; for (auto [v, i] : bt.tree[u]) if (v != p) { self(self, v, u); if (dir[v].second != -1 && dir[v].first < lca.depth[u]) { if (dir[u].second != -1 && dir[u].second != dir[v].second) assert(false); dir[u] = min(dir[u], dir[v]); } } }; string ret(m, 'B'); for (int u=0; u<o; u++) { if (!vis[u]) dfs(dfs, u, -1); if (dir[u].second != -1) { if (dir[u].second == 0 ^ bt.id[bt.edges[lca.par[u]].first] == u) ret[lca.par[u]] = 'L'; else ret[lca.par[u]] = 'R'; } } cout << ret << "\n"; return 0; }

Compilation message (stderr)

oneway.cpp: In function 'int main()':
oneway.cpp:210:31: warning: suggest parentheses around comparison in operand of '^' [-Wparentheses]
  210 |             if (dir[u].second == 0 ^ bt.id[bt.edges[lca.par[u]].first] == u)
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...