#include <vector>
#include <algorithm>
#include <iostream>
#include <set>
#include <cmath>
#include <map>
#include <random>
#include <cassert>
#include <ctime>
#include <cstdlib>
#include <queue>
#include <limits.h>
using namespace std;
class BridgeFinder {
public:
int n; // number of nodes
vector<vector<int>> adj; // adjacency list of graph
map<pair<int,int>,bool> isBridge;
vector<bool> visited;
vector<int> tin, low;
int timer;
void dfs(int v, int p = -1) {
visited[v] = true;
tin[v] = low[v] = timer++;
for (int to : adj[v]) {
if (to == p) continue;
if (visited[to]) {
low[v] = min(low[v], tin[to]);
} else {
dfs(to, v);
low[v] = min(low[v], low[to]);
if (low[to] > tin[v])
isBridge[{v, to}] = isBridge[{to, v}] = true;
}
}
}
void find_bridges() {
timer = 0;
visited.assign(n, false);
tin.assign(n, -1);
low.assign(n, -1);
for (int i = 0; i < n; ++i) {
if (!visited[i])
dfs(i);
}
for (int i = 0; i < adj.size(); i++) {
sort(adj[i].begin(), adj[i].end());
for (int j = 1; j < adj[i].size(); j++) {
if (adj[i][j] == adj[i][j - 1]) {
isBridge[{i, adj[i][j]}] = isBridge[{adj[i][j], i}] = false;
}
}
}
}
};
class DisjointSetUnion {
protected:
vector<int> parent;
vector<int> compSize;
const int n;
int connectedComponents;
public:
int getConnectedComponents() const {
return connectedComponents;
}
public:
DisjointSetUnion(int sz) : n(sz), connectedComponents(sz) {
parent.resize(sz), compSize.resize(sz);
for (int i = 0; i < n; i++) {
parent[i] = i, compSize[i] = 1;
}
}
int find_head(int x) const {
int cur = x;
while (cur != parent[cur]) {
cur = parent[cur];
}
return cur;
}
void join(int x, int y) {
x = find_head(x);
y = find_head(y);
if (x == y) {
return;
}
if (compSize[x] > compSize[y]) {
swap(x, y);
//ensures that compSize[x1] <= compSize[y1]
}
parent[x] = y;
compSize[y] += compSize[x];
connectedComponents--;
}
bool comp(int x, int y) {
return (find_head(x) == find_head(y));
}
};
class Graph {
public:
vector<vector<int>> adj;
vector<bool> hasVisited;
vector<vector<int>> tree_adj;
void dfs (int curNode) {
hasVisited[curNode] = true;
for (int i: adj[curNode]) {
if (!hasVisited[i]) {
tree_adj[curNode].push_back(i);
tree_adj[i].push_back(curNode);
dfs (i);
}
}
}
Graph (vector<vector<int>> adj) {
this->adj = adj;
hasVisited.assign(adj.size(), false);
tree_adj.resize(adj.size());
dfs(0);
}
};
struct segmentTree {
vector<int64_t> vec;
vector<int64_t> setLater;
void push(int v, int tl, int tr) {
if (setLater[v] == -1) {
return;
}
int tm = (tl + tr)/2;
setLater[2 * v + 1] = setLater[v];
vec[2 * v + 1] = setLater[v] * (tr - tm);
setLater[2 * v] = setLater[v];
vec[2 * v] = setLater[v] * (tm - tl + 1);
setLater[v] = -1;
}
const int64_t INF = 0;
int64_t upd(int dum, int tl, int tr, int l, int r, int64_t val) {
if (tr < l || tl > r) {
return INF;
}
if (tl >= l && tr <= r) {
setLater[dum] = val;
return (vec[dum] = val * (tr - tl + 1));
}
push(dum, tl, tr);
int mid = (tl + tr) >> 1;
upd(2 * dum, tl, mid, l, r, val);
upd(2 * dum + 1, mid + 1, tr, l, r, val);
return (vec[dum] = vec[2 * dum] + vec[2 * dum + 1]);
}
void upd(int l, int r, int val) {
upd(1, 0, (int) vec.size() / 2 - 1, l, r, val);
}
int64_t get(int dum, int tl, int tr, int &l, int &r) {
if (tl > r || tr < l) {
return INF;
}
if (tl >= l && tr <= r) {
return vec[dum];
}
push(dum, tl, tr);
int tm = (tl + tr) >> 1;
return get(dum * 2, tl, tm, l, r) + get(dum * 2 + 1, tm + 1, tr, l, r);
}
int64_t get(int l, int r) {
return get(1, 0, (int) vec.size() / 2 - 1, l, r);
}
void resz(int n) {
int sz = ((1 << (int) ceil(log2(n))));
vec.assign(sz * 2, 0);
setLater.assign(sz * 2, -1);
}
};
class HeavyLightDecomposition {
public:
vector<vector<int>> adj;
vector<int> sub;
vector<int> id;
vector<int> topchain;
vector<int> depth;
vector<int> parent;
segmentTree st;
vector<vector<int>> dp;
vector<int> en;
vector<int> ex;
int cntr = 0;
const int lg2 = 30;
void add_edge(int u, int v) {
adj[u].push_back(v), adj[v].push_back(u);
}
void rec(int curNode, int prevNode) {
parent[curNode] = prevNode;
en[curNode] = cntr++;
if (prevNode != -1) {
depth[curNode] = depth[prevNode] + 1;
} else {
depth[curNode] = 0;
}
sub[curNode] = 1;
for (int i: adj[curNode]) {
if (i != prevNode) {
rec(i, curNode);
sub[curNode] += sub[i];
}
}
ex[curNode] = cntr++;
}
HeavyLightDecomposition(int n) {
adj.resize(n);
sub.resize(n);
id.resize(n);
topchain.assign(n, -1);
parent.resize(n);
st.resz(n + 1);
ex.resize(n), en.resize(n);
}
void dfs(int curNode, int prevNode) {
id[curNode] = cntr++;
vector<pair<int, int>> vec;
for (int i: adj[curNode]) {
if (i != prevNode) {
vec.push_back({sub[i], i});
}
}
dp[curNode].resize(32);
dp[curNode][0] = max(prevNode, 0);
for (int i = 1; i < dp[curNode].size(); i++) {
dp[curNode][i] = dp[dp[curNode][i - 1]][i - 1];
}
if (!vec.empty()) {
sort(vec.begin(), vec.end());
reverse(vec.begin(), vec.end());
topchain[vec[0].second] = topchain[curNode];
for (int i = 1; i < vec.size(); i++) {
topchain[vec[i].second] = vec[i].second;
}
for (auto &p: vec) {
dfs(p.second, curNode);
}
}
}
void f (int a, int b, int d) {
if (a == b) {
return;
}
if (topchain[a] == topchain[b]) {
st.upd(id[b] + 1, id[a], d);
} else if (topchain[a] != a) {
st.upd(id[topchain[a]] + 1, id[a], d);
f(topchain[a], b, d);
} else {
st.upd(id[a], id[a], d);
f(parent[a], b, d);
}
}
bool isAncestor(int u, int v) {
return (en[u] <= en[v] && ex[u] >= ex[v]);
}
int leastCommonAncestor(int u, int v) {
if (isAncestor(u, v)) {
return u;
}
if (isAncestor(v, u)) {
return v;
}
for (int i = lg2; i >= 0; i--) {
if (!isAncestor(dp[u][i], v)) {
u = dp[u][i];
}
}
return dp[u][0];
}
void read() {
depth.resize(adj.size());
dp.resize(adj.size());
rec(0, -1); //fill in all of the subtrees
topchain[0] = 0;
cntr = 0;
dfs(0, -1); //fill in all of the ids and stuff
}
};
string ans;
void proccess (vector<pair<pair<int,int>,int>> edges, vector<pair<int,int>> queries) {
set<int> s;
for (auto& p: edges) s.insert(p.first.first), s.insert(p.first.second);
map<int,int> myMap; int cntr = 0;
for (int i: s) myMap[i] = cntr++;
for (int i = 0; i < edges.size(); i++) {
edges[i].first.first = myMap[edges[i].first.first], edges[i].first.second = myMap[edges[i].first.second];
}
for (int i = 0; i < queries.size(); i++) {
queries[i].first = myMap[queries[i].first], queries[i].second = myMap[queries[i].second];
}
vector<vector<int>> adj(s.size());
for (int i = 0; i < edges.size(); i++) {
adj[edges[i].first.first].push_back(edges[i].first.second);
adj[edges[i].first.second].push_back(edges[i].first.first);
}
BridgeFinder bf; bf.n = adj.size(); bf.adj = adj; bf.find_bridges();
Graph gr(adj);
adj = gr.tree_adj;
HeavyLightDecomposition hld(gr.tree_adj.size());
hld.adj = adj; hld.read();
for (int i = 0; i < queries.size(); i++) {
int lca = hld.leastCommonAncestor(queries[i].first, queries[i].second);
hld.f(queries[i].first, lca, 1);
hld.f(queries[i].second, lca, 2);
}
for (int i = 1; i < adj.size(); i++) {
if (!bf.isBridge[{i, hld.parent[i]}]) {
hld.st.upd(hld.id[i], hld.id[i], 0);
}
}
for (int i = 0; i < edges.size(); i++) {
int nd;
if (hld.isAncestor(edges[i].first.second, edges[i].first.first)) {
nd = edges[i].first.first;
} else {
nd = edges[i].first.second;
}
if (hld.st.get(hld.id[nd], hld.id[nd]) == 0) {
ans[edges[i].second] = 'B';
} else if (hld.st.get(hld.id[nd], hld.id[nd]) == 1) {
if (nd == edges[i].first.first) ans[edges[i].second] = 'R';
else ans[edges[i].second] = 'L';
} else {
if (nd == edges[i].first.first) ans[edges[i].second] = 'L';
else ans[edges[i].second] = 'R';
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N, M;
cin >> N >> M;
vector<pair<pair<int,int>,int>> edges;
DisjointSetUnion dsu(N);
map<pair<int,int>,int> cnt;
for (int i = 0; i < M; i++) {
int u, v;
cin >> u >> v;
u--, v--;
cnt[{u, v}]++, cnt[{v, u}]++;
assert(u != v);
edges.emplace_back(make_pair(u, v), i), dsu.join(u, v);
}
int Q; cin >> Q; vector<pair<int,int>> queries;
for (int i = 0; i < Q; i++) {
int u, v; cin >> u >> v; u--, v--;
queries.emplace_back(u, v);
}
vector<pair<pair<int,int>,int>> edges1[N];
vector<pair<int,int>> queries1[N];
for (int i = 0; i < M; i++) {
edges1[dsu.find_head(edges[i].first.first)].push_back(edges[i]);
}
for (int i = 0; i < Q; i++) {
queries1[dsu.find_head(queries[i].first)].push_back(queries[i]);
}
ans.assign(edges.size(), '?');
for (int i = 0; i < N; i++) {
if (!edges1[i].empty()) {
proccess(edges1[i], queries1[i]);
}
}
for (int i = 0; i < edges.size(); i++) {
if (cnt[edges[i].first] >= 2) {
ans[i] = 'B';
}
}
cout << ans << '\n';
}
Compilation message
oneway.cpp: In member function 'void BridgeFinder::find_bridges()':
oneway.cpp:49:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
49 | for (int i = 0; i < adj.size(); i++) {
| ~~^~~~~~~~~~~~
oneway.cpp:51:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
51 | for (int j = 1; j < adj[i].size(); j++) {
| ~~^~~~~~~~~~~~~~~
oneway.cpp: In member function 'void HeavyLightDecomposition::dfs(int, int)':
oneway.cpp:244:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
244 | for (int i = 1; i < dp[curNode].size(); i++) {
| ~~^~~~~~~~~~~~~~~~~~~~
oneway.cpp:251:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
251 | for (int i = 1; i < vec.size(); i++) {
| ~~^~~~~~~~~~~~
oneway.cpp: In function 'void proccess(std::vector<std::pair<std::pair<int, int>, int> >, std::vector<std::pair<int, int> >)':
oneway.cpp:312:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<std::pair<int, int>, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
312 | for (int i = 0; i < edges.size(); i++) {
| ~~^~~~~~~~~~~~~~
oneway.cpp:315:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
315 | for (int i = 0; i < queries.size(); i++) {
| ~~^~~~~~~~~~~~~~~~
oneway.cpp:319:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<std::pair<int, int>, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
319 | for (int i = 0; i < edges.size(); i++) {
| ~~^~~~~~~~~~~~~~
oneway.cpp:328:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
328 | for (int i = 0; i < queries.size(); i++) {
| ~~^~~~~~~~~~~~~~~~
oneway.cpp:333:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
333 | for (int i = 1; i < adj.size(); i++) {
| ~~^~~~~~~~~~~~
oneway.cpp:338:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<std::pair<int, int>, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
338 | for (int i = 0; i < edges.size(); i++) {
| ~~^~~~~~~~~~~~~~
oneway.cpp: In function 'int main()':
oneway.cpp:393:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<std::pair<int, int>, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
393 | for (int i = 0; i < edges.size(); i++) {
| ~~^~~~~~~~~~~~~~
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
2 ms |
852 KB |
Output is correct |
4 |
Correct |
4 ms |
1236 KB |
Output is correct |
5 |
Correct |
3 ms |
1236 KB |
Output is correct |
6 |
Correct |
2 ms |
812 KB |
Output is correct |
7 |
Correct |
3 ms |
1236 KB |
Output is correct |
8 |
Correct |
3 ms |
1236 KB |
Output is correct |
9 |
Correct |
2 ms |
816 KB |
Output is correct |
10 |
Correct |
2 ms |
852 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
2 ms |
852 KB |
Output is correct |
4 |
Correct |
4 ms |
1236 KB |
Output is correct |
5 |
Correct |
3 ms |
1236 KB |
Output is correct |
6 |
Correct |
2 ms |
812 KB |
Output is correct |
7 |
Correct |
3 ms |
1236 KB |
Output is correct |
8 |
Correct |
3 ms |
1236 KB |
Output is correct |
9 |
Correct |
2 ms |
816 KB |
Output is correct |
10 |
Correct |
2 ms |
852 KB |
Output is correct |
11 |
Correct |
297 ms |
34140 KB |
Output is correct |
12 |
Correct |
332 ms |
42928 KB |
Output is correct |
13 |
Correct |
486 ms |
58996 KB |
Output is correct |
14 |
Correct |
482 ms |
77444 KB |
Output is correct |
15 |
Correct |
571 ms |
81340 KB |
Output is correct |
16 |
Correct |
643 ms |
96816 KB |
Output is correct |
17 |
Correct |
615 ms |
100340 KB |
Output is correct |
18 |
Correct |
673 ms |
96816 KB |
Output is correct |
19 |
Correct |
612 ms |
102712 KB |
Output is correct |
20 |
Correct |
426 ms |
57088 KB |
Output is correct |
21 |
Correct |
314 ms |
56264 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
2 ms |
852 KB |
Output is correct |
4 |
Correct |
4 ms |
1236 KB |
Output is correct |
5 |
Correct |
3 ms |
1236 KB |
Output is correct |
6 |
Correct |
2 ms |
812 KB |
Output is correct |
7 |
Correct |
3 ms |
1236 KB |
Output is correct |
8 |
Correct |
3 ms |
1236 KB |
Output is correct |
9 |
Correct |
2 ms |
816 KB |
Output is correct |
10 |
Correct |
2 ms |
852 KB |
Output is correct |
11 |
Correct |
297 ms |
34140 KB |
Output is correct |
12 |
Correct |
332 ms |
42928 KB |
Output is correct |
13 |
Correct |
486 ms |
58996 KB |
Output is correct |
14 |
Correct |
482 ms |
77444 KB |
Output is correct |
15 |
Correct |
571 ms |
81340 KB |
Output is correct |
16 |
Correct |
643 ms |
96816 KB |
Output is correct |
17 |
Correct |
615 ms |
100340 KB |
Output is correct |
18 |
Correct |
673 ms |
96816 KB |
Output is correct |
19 |
Correct |
612 ms |
102712 KB |
Output is correct |
20 |
Correct |
426 ms |
57088 KB |
Output is correct |
21 |
Correct |
314 ms |
56264 KB |
Output is correct |
22 |
Correct |
942 ms |
103884 KB |
Output is correct |
23 |
Correct |
1123 ms |
100272 KB |
Output is correct |
24 |
Correct |
1180 ms |
100312 KB |
Output is correct |
25 |
Correct |
820 ms |
110388 KB |
Output is correct |
26 |
Correct |
954 ms |
102868 KB |
Output is correct |
27 |
Correct |
1043 ms |
100496 KB |
Output is correct |
28 |
Correct |
140 ms |
11920 KB |
Output is correct |
29 |
Correct |
665 ms |
59844 KB |
Output is correct |
30 |
Correct |
593 ms |
60316 KB |
Output is correct |
31 |
Correct |
676 ms |
60896 KB |
Output is correct |
32 |
Correct |
571 ms |
73592 KB |
Output is correct |