제출 #35892

#제출 시각아이디문제언어결과실행 시간메모리
35892funcsrOne-Way Streets (CEOI17_oneway)C++14
100 / 100
363 ms23852 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#define pb push_back
#define all(xs) xs.begin(), xs.end()
#define rep(i, n) for (int i=0; i<(n); i++)
using namespace std;
typedef pair<int, int> P;
#define _1 first
#define _2 second
struct UnionFind {
  int N;
  vector<int> U, R;
  UnionFind(int N) : N(N), U(N), R(N) {
    rep(i, N) U[i] = i, R[i] = 1;
  }
  int find(int x) {
    if (U[x] == x) return x;
    return U[x] = find(U[x]);
  }
  void unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return;
    if (R[x] < R[y]) swap(x, y);
    U[y] = x;
    R[x] += R[y];
  }
};

int N, M, K;
vector<P> G[100000];
P E[100000];
bool bridge[100000];
bool up[100000], down[100000];

int R[100000], T[100000];
bool used[100000];
void dfs(int x, int p, int r) {
  used[x] = true;
  R[x] = r;
  for (P pp : G[x]) {
    int t = pp._1, pi = pp._2;
    if (pi == p) continue;
    if (used[t]) {
      if (R[t] < R[x]) T[t]++, T[x]--;
      continue;
    }
    dfs(t, pi, r+1);
  }
}
void dfs2(int x, int p) {
  used[x] = true;
  for (P pp : G[x]) {
    int t = pp._1, pi = pp._2;
    if (pi == p || used[t]) continue;
    dfs2(t, pi);
    T[x] += T[t];
  }
  if (p != -1 && T[x] == 0) bridge[p] = true;
}

int U[20][100000];
int W[2][100000];
void dfs3(int x, int p, int r) {
  used[x] = true;
  U[0][x] = p;
  R[x] = r;
  for (P pp : G[x]) {
    int t = pp._1;
    if (t == p) continue;
    dfs3(t, x, r+1);
  }
}
int lca(int x, int y) {
  if (R[x] < R[y]) swap(x, y);
  for (int k=19; k>=0; k--) if (((R[x]-R[y])>>k)&1) x = U[k][x];
  if (x == y) return x;
  for (int k=19; k>=0; k--) if (U[k][x] != U[k][y]) x = U[k][x], y = U[k][y];
  return U[0][x];
}
void dfs4(int x, int p, int pe) {
  for (P pp : G[x]) {
    int t = pp._1;
    if (t == p) continue;
    dfs4(t, x, pp._2);
    W[0][x] += W[0][t];
    W[1][x] += W[1][t];
  }
  if (p != -1) {
    assert(!W[0][x] || !W[1][x]);
    if      (W[0][x]) up[pe] = true;
    else if (W[1][x]) down[pe] = true;
    else up[pe] = down[pe] = true;
  }
}

signed main() {
  cin >> N >> M;
  rep(i, M) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    E[i] = P(a, b);
    if (a == b) {
      up[i] = down[i] = true;
      continue;
    }
    G[a].pb(P(b, i));
    G[b].pb(P(a, i));
  }
  rep(i, N) used[i] = false;
  rep(i, N) if (!used[i]) dfs(i, -1, 0);
  rep(i, N) used[i] = false;
  rep(i, N) if (!used[i]) dfs2(i, -1);

  // build a tree
  rep(i, N) G[i].clear();
  //rep(i, M) if(bridge[i])cout<<"i="<<i<<": "<<E[i]._1<<","<<E[i]._2<<" is a bridge\n";
  UnionFind uf(N);
  rep(i, M) if (!bridge[i]) {
    up[i] = down[i] = true;
    uf.unite(E[i]._1, E[i]._2);
  }
  rep(i, M) if (bridge[i]) {
    int u = uf.find(E[i]._1), v = uf.find(E[i]._2);
    G[u].pb(P(v, i));
    G[v].pb(P(u, i));
  }
  vector<int> roots;
  rep(i, N) used[i] = false;
  rep(i, N) if (uf.find(i) == i && !used[i]) dfs3(i, -1, 0), roots.pb(i);
  rep(k, 19) {
    rep(i, N) {
      if (uf.find(i) != i) continue;
      if (U[k][i] == -1) U[k+1][i] = -1;
      U[k+1][i] = U[k][U[k][i]];
    }
  }
  cin >> K;
  rep(i, K) {
    int x, y;
    cin >> x >> y;
    x--, y--;
    x = uf.find(x), y = uf.find(y);
    if (x == y) continue;
    int g = lca(x, y);
    W[0][x]++, W[0][g]--; // x->g
    W[1][y]++, W[1][g]--; // y->g
  }
  for (int x : roots) dfs4(x, -1, -1);
  rep(i, M) if (bridge[i]) {
    int u = uf.find(E[i]._1), v = uf.find(E[i]._2);
    if (R[v] < R[u]) swap(up[i], down[i]);
  }

  rep(i, M) {
    assert(up[i] || down[i]);
    if (up[i] && down[i]) cout << 'B';
    else if (up[i]) cout << 'L';
    else if (down[i]) cout << 'R';
  }
  cout << '\n';
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...