Submission #231480

# Submission time Handle Problem Language Result Execution time Memory
231480 2020-05-13T17:57:51 Z rqi One-Way Streets (CEOI17_oneway) C++14
30 / 100
3000 ms 256024 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++){
            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];
int 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);
            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);
    }

    //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 9 ms 7552 KB Output is correct
2 Correct 9 ms 7552 KB Output is correct
3 Correct 9 ms 7680 KB Output is correct
4 Correct 9 ms 7680 KB Output is correct
5 Correct 9 ms 7808 KB Output is correct
6 Correct 9 ms 7680 KB Output is correct
7 Correct 10 ms 7808 KB Output is correct
8 Correct 9 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 9 ms 7552 KB Output is correct
2 Correct 9 ms 7552 KB Output is correct
3 Correct 9 ms 7680 KB Output is correct
4 Correct 9 ms 7680 KB Output is correct
5 Correct 9 ms 7808 KB Output is correct
6 Correct 9 ms 7680 KB Output is correct
7 Correct 10 ms 7808 KB Output is correct
8 Correct 9 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 56 ms 16096 KB Output is correct
12 Correct 64 ms 18424 KB Output is correct
13 Correct 74 ms 21884 KB Output is correct
14 Correct 99 ms 26720 KB Output is correct
15 Correct 99 ms 27764 KB Output is correct
16 Correct 113 ms 28924 KB Output is correct
17 Correct 107 ms 31480 KB Output is correct
18 Correct 114 ms 29176 KB Output is correct
19 Correct 104 ms 32888 KB Output is correct
20 Correct 67 ms 20344 KB Output is correct
21 Execution timed out 3086 ms 256024 KB Time limit exceeded
# Verdict Execution time Memory Grader output
1 Correct 9 ms 7552 KB Output is correct
2 Correct 9 ms 7552 KB Output is correct
3 Correct 9 ms 7680 KB Output is correct
4 Correct 9 ms 7680 KB Output is correct
5 Correct 9 ms 7808 KB Output is correct
6 Correct 9 ms 7680 KB Output is correct
7 Correct 10 ms 7808 KB Output is correct
8 Correct 9 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 56 ms 16096 KB Output is correct
12 Correct 64 ms 18424 KB Output is correct
13 Correct 74 ms 21884 KB Output is correct
14 Correct 99 ms 26720 KB Output is correct
15 Correct 99 ms 27764 KB Output is correct
16 Correct 113 ms 28924 KB Output is correct
17 Correct 107 ms 31480 KB Output is correct
18 Correct 114 ms 29176 KB Output is correct
19 Correct 104 ms 32888 KB Output is correct
20 Correct 67 ms 20344 KB Output is correct
21 Execution timed out 3086 ms 256024 KB Time limit exceeded