제출 #958427

#제출 시각아이디문제언어결과실행 시간메모리
958427dio_2One-Way Streets (CEOI17_oneway)C++17
0 / 100
0 ms348 KiB
#include<bits/stdc++.h> using namespace std; using pii = pair<int, int>; // DESCRIPTION // Given an undirected graph returns a forest // where every node in a tree is a potential SCC in the initial graph. // Works with multi-edges and disconnected components. // Doesnt acctually orient the edges to make the SCC since // The forest only considers them as nodes. // You don't really have a connection with the previous graph. // 0 - indexed. // check: https://codeforces.com/contest/555/problem/E. // Watch out for: // 1) multi-edges. // 2) how many components. // 3) carefull implementation. vector<vector<int>> Get2EdgeForest(vector<vector<pii>> &g, int n, int m, int &N, vector<int> &labels, vector<pii> &bri){ vector<int> vis(n), dep(n), is_span(m), dp(n), is_bridge(m); vector<vector<int>> gA(n), gB(n); vector<pii> bridges; // finding bridges and marking them auto dfs = [&](auto &&dfs, int u, int p, int id)->void{ vis[u] = 1; for(auto [v, i] : g[u]) if(!vis[v]){ dep[v] = dep[u] + 1; is_span[i] = 1; dfs(dfs, v, u, i); // DFS AFTER DEPTH CALCULATION!!!!!!!. } int cnt_par = 0; set<int> s; // UGLY with sets can be done without ' em. for(auto [v, i] : g[u]){ if(v == p){ cnt_par += 1; continue; } if(s.count(v)) continue; s.insert(v); if(is_span[i]) dp[u] += dp[v]; if(!is_span[i] && dep[v] > dep[u]) dp[u]--; if(!is_span[i] && dep[v] < dep[u]) dp[u]++; } // cnt_par == 1 needed for multiple edges. if(dp[u] == 0 && p != -1 && cnt_par == 1){ bridges.emplace_back(u, p); is_bridge[id] = 1; } }; for(int i = 0;i < n;i++){ if(!vis[i]){ dfs(dfs, i, -1, -1); } } // ceating a second graph without bridges for(int i = 0;i < n;i++){ for(auto [j, id] : g[i]){ if(is_bridge[id]) continue; gA[i].push_back(j); } } vector<int> label(n); fill(vis.begin(), vis.end(), false); int cnt = 0; // merge nodes. auto dfs2 = [&](auto &&dfs2, int u)->void{ vis[u] = 1; label[u] = cnt; for(int v : gA[u]){ if(!vis[v]){ dfs2(dfs2, v); } } }; for(int i = 0;i < n;i++){ if(!vis[i]){ dfs2(dfs2, i); cnt++; } } // create the tree. for(auto [u, v] : bridges){ int orgu = u, orgv = v; u = label[u]; v = label[v]; if(u == v) continue; bri.emplace_back(orgu, orgv); gB[u].push_back(v); gB[v].push_back(u); } N = cnt; labels = label; return gB; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<vector<pair<int, int>>> g(n); string ans(m, 'B'); for(int i = 0;i < m;i++){ int a, b; cin >> a >> b, --a, --b; if(a == b){ ans[i] = 'B'; } else { g[a].emplace_back(b, i); g[b].emplace_back(a, i); } } int p; cin >> p; vector<pair<int, int>> a(p); for(int i = 0;i < p;i++){ int x, y; cin >> x >> y, --x, --y; a[i] = make_pair(x, y); } int N; vector<int> labels; vector<pii> bri; map<pii, pii> mapka; vector<vector<int>> new_g = Get2EdgeForest(g, n, m, N, labels, bri); vector<bool> vis(N); for(auto [x, y] : bri) mapka[make_pair(labels[x], labels[y])] = make_pair(x, y); const int LOG = 20; vector<vector<int>> up(N, vector<int> (LOG)); vector<int> dep(N); vector<int> L(N), A(N), B(N); auto dfs = [&](auto &&dfs, int u, int p)->void{ for(int v : new_g[u]) if(v != p){ dep[v] = dep[u] + 1; up[v][0] = u; for(int i = 1;i < LOG;i++) up[v][i] = up[ up[v][i - 1] ][i - 1]; dfs(dfs, v, u); } }; auto lca = [&](int u, int v)->int{ if(dep[u] > dep[v]) swap(v, u); int k = dep[v] - dep[u]; for(int i = LOG - 1;i >= 0;i--){ if((k >> i) & 1) v = up[v][i]; } assert(dep[v] == dep[u]); if(v == u) return v; for(int i = LOG - 1;i >= 0;i--){ if(up[v][i] != up[u][i]){ u = up[u][i]; v = up[v][i]; } } return up[v][0]; }; for(int i = 0;i < N;i++){ if(!vis[i]){ for(int j = 0;j < LOG;j++) up[i][j] = i; dfs(dfs, i, -1); } } for(auto &[x, y] : a){ // x -> y. x = labels[x]; y = labels[y]; int l = lca(x, y); if(x == y) continue; L[l]++; A[x]++; B[y]++; } auto dfs2 = [&](auto &&dfs2, int u, int p)->void{ for(int v : new_g[u]) if(v != p){ dfs2(dfs2, v, u); A[u] += A[v]; B[u] += B[v]; } if(p != -1){ assert(not(A[u] - L[u] > 0 && B[u] - L[u] > 0)); } }; for(int i = 0;i < N;i++){ if(dep[i] == 0){ dfs2(dfs2, i, -1); } } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...