Submission #231481

# Submission time Handle Problem Language Result Execution time Memory
231481 2020-05-13T18:16:46 Z rqi One-Way Streets (CEOI17_oneway) C++14
100 / 100
231 ms 36856 KB
#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
typedef long double ld;
typedef double db; 
typedef string str; 

typedef pair<int,int> pi;
typedef pair<ll,ll> pl; 
typedef pair<db,db> pd; 

typedef vector<int> vi; 
typedef vector<ll> vl; 
typedef vector<db> vd; 
typedef vector<str> vs; 
typedef vector<pi> vpi;
typedef vector<pl> vpl; 
typedef vector<pd> vpd; 

#define mp make_pair 
#define f first
#define s second
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend() 
#define rsz resize
#define ins insert 
#define ft front() 
#define bk back()
#define pf push_front 
#define pb push_back
#define eb emplace_back 
#define lb lower_bound 
#define ub upper_bound 

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

const int MOD = 1e9+7; // 998244353;
const int MX = 2e5+5; 
const ll INF = 1e18; 
const ld PI = acos((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1}; 

template<class T> bool ckmin(T& a, const T& b) { 
    return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { 
    return a < b ? a = b, 1 : 0; } 
int pct(int x) { return __builtin_popcount(x); } 
int bit(int x) { return 31-__builtin_clz(x); } // floor(log2(x)) 
int cdiv(int a, int b) { return a/b+!(a<0||a%b == 0); } // division of a by b rounded up, assumes b > 0 

// INPUT
template<class A> void re(complex<A>& c);
template<class A, class B> void re(pair<A,B>& p);
template<class A> void re(vector<A>& v);
template<class A, size_t SZ> void re(array<A,SZ>& a);

template<class T> void re(T& x) { cin >> x; }
void re(db& d) { str t; re(t); d = stod(t); }
void re(ld& d) { str t; re(t); d = stold(t); }
template<class H, class... T> void re(H& h, T&... t) { re(h); re(t...); }

template<class A> void re(complex<A>& c) { A a,b; re(a,b); c = {a,b}; }
template<class A, class B> void re(pair<A,B>& p) { re(p.f,p.s); }
template<class A> void re(vector<A>& x) { trav(a,x) re(a); }
template<class A, size_t SZ> void re(array<A,SZ>& x) { trav(a,x) re(a); }

// TO_STRING
#define ts to_string
template<class A, class B> str ts(pair<A,B> p);
template<class A> str ts(complex<A> c) { return ts(mp(c.real(),c.imag())); }
str ts(bool b) { return b ? "true" : "false"; }
str ts(char c) { str s = ""; s += c; return s; }
str ts(str s) { return s; }
str ts(const char* s) { return (str)s; }
str ts(vector<bool> v) { 
    bool fst = 1; str res = "{";
    F0R(i,sz(v)) {
        if (!fst) res += ", ";
        fst = 0; res += ts(v[i]);
    }
    res += "}"; return res;
}
template<size_t SZ> str ts(bitset<SZ> b) {
    str res = ""; F0R(i,SZ) res += char('0'+b[i]);
    return res; }
template<class T> str ts(T v) {
    bool fst = 1; str res = "{";
    for (const auto& x: v) {
        if (!fst) res += ", ";
        fst = 0; res += ts(x);
    }
    res += "}"; return res;
}
template<class A, class B> str ts(pair<A,B> p) {
    return "("+ts(p.f)+", "+ts(p.s)+")"; }

// OUTPUT
template<class A> void pr(A x) { cout << ts(x); }
template<class H, class... T> void pr(const H& h, const T&... t) { 
    pr(h); pr(t...); }
void ps() { pr("\n"); } // print w/ spaces
template<class H, class... T> void ps(const H& h, const T&... t) { 
    pr(h); if (sizeof...(t)) pr(" "); ps(t...); }

// DEBUG
void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
    cerr << to_string(h); if (sizeof...(t)) cerr << ", ";
    DBG(t...); }
#ifdef LOCAL // compile with -DLOCAL
#define dbg(...) cerr << "[" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#else
#define dbg(...) 42
#endif

// FILE I/O
void setIn(string s) { freopen(s.c_str(),"r",stdin); }
void setOut(string s) { freopen(s.c_str(),"w",stdout); }
void unsyncIO() { ios_base::sync_with_stdio(0); cin.tie(0); }
void setIO(string s = "") {
    unsyncIO();
    // cin.exceptions(cin.failbit); 
    // throws exception when do smth illegal
    // ex. try to read letter into int
    if (sz(s)) { setIn(s+".in"), setOut(s+".out"); } // for USACO
}

mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()); 


/**
 * Description: Disjoint Set Union with path compression. 
     * Add edges and test connectivity. Use for Kruskal's 
     * minimum spanning tree.
 * Time: O(\alpha(N))
 * Source: CSAcademy, KACTL
 * Verification: USACO superbull
 */

struct DSU {
    vi e; void init(int n) { e = vi(n,-1); }
    int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); } 
    bool sameSet(int a, int b) { return get(a) == get(b); }
    int size(int x) { return -e[get(x)]; }
    bool unite(int x, int y) { // union-by-rank
        x = get(x), y = get(y); if (x == y) return 0;
        if (e[x] > e[y]) swap(x,y);
        e[x] += e[y]; e[y] = x; return 1;
    }
};

/**template<class T> T kruskal(int n, vector<pair<T,pi>> ed) {
    sort(all(ed));
    T ans = 0; DSU D; D.init(n+1); // edges that unite are in MST
    trav(a,ed) if (D.unite(a.s.f,a.s.s)) ans += a.f; 
    return ans;
}*/




/**
 * Description: Calculates least common ancestor in tree 
     * with root $R$ using binary jumping. 
 * Time: O(N\log N) build, O(\log N) query
 * Source: USACO Camp
 * Verification: Debug the Bugs
 */

template<int SZ> struct LCA {
    static const int BITS = 32-__builtin_clz(SZ);
    int N = 1, par[BITS][SZ], depth[SZ], mind[SZ][2];
    int ind[SZ]; //index of edge from i to par[i]
    vpi adj[SZ]; 
    /// INITIALIZE
    void ae(int u, int v, int i) { adj[u].pb(mp(v, i)), adj[v].pb(mp(u, i)); }
    void dfs(int u, int prev, int index = 0){
        ind[u] = index;
        par[0][u] = prev; depth[u] = depth[prev]+1;
        trav(v,adj[u]) if (v.f != prev) dfs(v.f, u, v.s);
    }
    void propmind(int node, int prv){
        for(auto u: adj[node]){
            if(u.f == prv) continue;
            propmind(u.f, node);
            for(int j = 0; j < 2; j++){
                ckmin(mind[node][j], mind[u.f][j]);
            }
            
        }
    }

    void init(int _N) {
        N = _N; 
        for(int i = 1; i <= N; i++){
            //dbg(i);
            mind[i][0] = mind[i][1] = MOD;
            if(depth[i] == 0) dfs(i, 0);
        }

        FOR(k,1,BITS) FOR(i,1,N+1) 
            par[k][i] = par[k-1][par[k-1][i]];
    }


    /// QUERY
    int getPar(int a, int b) {
        R0F(k,BITS) if (b&(1<<k)) a = par[k][a];
        return a; }
    int lca(int u, int v){
        if (depth[u] < depth[v]) swap(u,v);
        u = getPar(u,depth[u]-depth[v]);
        R0F(k,BITS) if (par[k][u] != par[k][v]) 
            u = par[k][u], v = par[k][v];
        return u == v ? u : par[0][u];
    }
    int dist(int u, int v) {
        return depth[u]+depth[v]-2*depth[lca(u,v)]; }
};

const int mx = 100005;
int n, m, p;
pi elist[mx];
int dir[mx]; //0 = both, 1 = right, 2 = left
vpi adj[mx];
pi cond[mx];

bool visited[mx];
bool processed[mx];

int dist[mx];
int mindepth[mx];
int par[mx];
vi child[mx];

DSU dsu;
LCA<100105> lca;

void genDFS(int node, int d = 0){
    //dbg(node, d);
    visited[node] = 1;
    dist[node] = d;
    for(auto u: adj[node]){
        if(processed[u.s] == 1) continue;
        processed[u.s] = 1;
        if(visited[u.f] == 1){
            //backedge
            //dbg(node, u.f);
            ckmin(mindepth[node], dist[u.f]);
            continue;
        }
        child[node].pb(u.f);
        par[u.f] = node;
        genDFS(u.f, d+1);
    }
}

void propMinDepth(int node){
    for(auto u: child[node]){
        propMinDepth(u);
        ckmin(mindepth[node], mindepth[u]);
    }
}

int main() {
    setIO();
    //#warning self & double edges?
    //Input
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int a, b;
        cin >> a >> b;
        elist[i] = mp(a, b);
        if(a == b) continue; //take care of self edges
        adj[a].pb(mp(b, i));
        adj[b].pb(mp(a, i));
    }

    int p;
    cin >> p;

    for(int i = 1; i <= p; i++){
        int x, y;
        cin >> x >> y;
        cond[i] = mp(x, y);
    }

    //Generate dfs forest with depths & parent. When backedge occurs, put mindepth on that node. 

    for(int i = 1; i <= n; i++) mindepth[i] = MOD;
    for(int i = 1; i <= n; i++){
        if(visited[i] == 1) continue;
        genDFS(i);
    }


    //mindepth of every node becomes min of mindepth of all its children


    for(int i = 1; i <= n; i++){
        if(dist[i] == 0) propMinDepth(i);
    }

    //for(int i = 1; i <= n; i++) dbg(i, mindepth[i]);

    //If mindepth < depth, merge and its parent in the DSU.

    dsu.init(n+5);
    for(int i = 1; i <= n; i++){
        //dbg(i, par[i]);
        if(mindepth[i] < dist[i]){
            //dbg(i, par[i]);
            dsu.unite(i, par[i]);
        }
    }


    //create LCA forest with new edges with dsu.get(), init. Probably change init
    for(int i = 1; i <= m; i++){
        elist[i].f = dsu.get(elist[i].f);
        elist[i].s = dsu.get(elist[i].s);
        int a = elist[i].f;
        int b = elist[i].s;
        if(a != b){
            lca.ae(a, b, i);
            //dbg(a, b, i);
        }
    }

    lca.init(n);



    //Upedges from a to lca, downedges from lca to b.
    
    //for(int i = 1; i <= n; i++) dbg(i, lca.depth[i]);

    for(int i = 1; i <= p; i++){
        pi u = cond[i];
        int a = dsu.get(u.f);
        int b = dsu.get(u.s);
        int c = lca.lca(a, b);
        //dbg(u, a, b, c);
        ckmin(lca.mind[a][0], lca.depth[c]); //up
        ckmin(lca.mind[b][1], lca.depth[c]); //down
        //dbg(a, c);
        //dbg(b, c);
    }


    //mindepth (for up & down) becomes min of mindepth for all its children
    for(int i = 1; i <= n; i++){
        if(lca.depth[i] == 1){
            lca.propmind(i, 0);
        }
    }

    //for(int i = 1; i <= n; i++) dbg(i, lca.mind[i][0], lca.mind[i][1]);
    
    //If mindepth < depth for up/down, direct the edge up/down. 
    for(int i = 1; i <= n; i++){
        int z = lca.ind[i];
        if(z == 0) continue;
        for(int j = 0; j < 2; j++){
            if(lca.mind[i][j] < lca.depth[i]){
                
                int fac = 1;
                if(elist[z].f == i) fac = 0;
                //dbg(i, j, z, elist[z]);
                fac^=j;
                if(fac == 0){
                    dir[z] = 1;
                }
                else dir[z] = 2;
                /*if(elist[z].f == i){
                    //if j == 0, direct it right
                    //if j == 1, direct it left
                }
                else{
                    //if j == 0, direct it left
                    //if j == 1, direct it right
                }*/
            }
        }
    }


    //Go through original edgelist and print
    
    for(int i = 1; i <= m; i++){
        if(dir[i] == 0) cout << 'B';
        else if(dir[i] == 1) cout << 'R';
        else cout << 'L';
    }
    cout << "\n";



    // you should actually read the stuff at the bottom
}

/* stuff you should look for
    * int overflow, array bounds
    * special cases (n=1?)
    * do smth instead of nothing and stay organized
    * WRITE STUFF DOWN
*/

Compilation message

oneway.cpp: In function 'void setIn(std::__cxx11::string)':
oneway.cpp:123:31: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
 void setIn(string s) { freopen(s.c_str(),"r",stdin); }
                        ~~~~~~~^~~~~~~~~~~~~~~~~~~~~
oneway.cpp: In function 'void setOut(std::__cxx11::string)':
oneway.cpp:124:32: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
 void setOut(string s) { freopen(s.c_str(),"w",stdout); }
                         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 8 ms 7552 KB Output is correct
2 Correct 8 ms 7552 KB Output is correct
3 Correct 9 ms 7552 KB Output is correct
4 Correct 9 ms 7808 KB Output is correct
5 Correct 9 ms 7808 KB Output is correct
6 Correct 9 ms 7680 KB Output is correct
7 Correct 9 ms 7808 KB Output is correct
8 Correct 10 ms 7808 KB Output is correct
9 Correct 9 ms 7680 KB Output is correct
10 Correct 9 ms 7680 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 8 ms 7552 KB Output is correct
2 Correct 8 ms 7552 KB Output is correct
3 Correct 9 ms 7552 KB Output is correct
4 Correct 9 ms 7808 KB Output is correct
5 Correct 9 ms 7808 KB Output is correct
6 Correct 9 ms 7680 KB Output is correct
7 Correct 9 ms 7808 KB Output is correct
8 Correct 10 ms 7808 KB Output is correct
9 Correct 9 ms 7680 KB Output is correct
10 Correct 9 ms 7680 KB Output is correct
11 Correct 51 ms 14968 KB Output is correct
12 Correct 61 ms 17400 KB Output is correct
13 Correct 75 ms 20688 KB Output is correct
14 Correct 92 ms 25208 KB Output is correct
15 Correct 104 ms 26612 KB Output is correct
16 Correct 116 ms 27704 KB Output is correct
17 Correct 110 ms 30200 KB Output is correct
18 Correct 118 ms 28152 KB Output is correct
19 Correct 103 ms 31608 KB Output is correct
20 Correct 66 ms 19192 KB Output is correct
21 Correct 63 ms 18936 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 8 ms 7552 KB Output is correct
2 Correct 8 ms 7552 KB Output is correct
3 Correct 9 ms 7552 KB Output is correct
4 Correct 9 ms 7808 KB Output is correct
5 Correct 9 ms 7808 KB Output is correct
6 Correct 9 ms 7680 KB Output is correct
7 Correct 9 ms 7808 KB Output is correct
8 Correct 10 ms 7808 KB Output is correct
9 Correct 9 ms 7680 KB Output is correct
10 Correct 9 ms 7680 KB Output is correct
11 Correct 51 ms 14968 KB Output is correct
12 Correct 61 ms 17400 KB Output is correct
13 Correct 75 ms 20688 KB Output is correct
14 Correct 92 ms 25208 KB Output is correct
15 Correct 104 ms 26612 KB Output is correct
16 Correct 116 ms 27704 KB Output is correct
17 Correct 110 ms 30200 KB Output is correct
18 Correct 118 ms 28152 KB Output is correct
19 Correct 103 ms 31608 KB Output is correct
20 Correct 66 ms 19192 KB Output is correct
21 Correct 63 ms 18936 KB Output is correct
22 Correct 231 ms 33184 KB Output is correct
23 Correct 210 ms 31096 KB Output is correct
24 Correct 230 ms 30840 KB Output is correct
25 Correct 227 ms 36856 KB Output is correct
26 Correct 226 ms 32504 KB Output is correct
27 Correct 216 ms 31096 KB Output is correct
28 Correct 55 ms 12536 KB Output is correct
29 Correct 96 ms 21496 KB Output is correct
30 Correct 107 ms 21880 KB Output is correct
31 Correct 107 ms 22008 KB Output is correct
32 Correct 161 ms 27128 KB Output is correct