Submission #1116702

#TimeUsernameProblemLanguageResultExecution timeMemory
1116702Zero_OPJail (JOI22_jail)C++14
100 / 100
3107 ms1006552 KiB
#include <bits/stdc++.h>

using namespace std;

#define dbg(x) "[" #x " = " << (x) << "]"

bool cycle_detection(vector<vector<int>>& adj){
    int N = (int)adj.size();
    vector<int> vis(N);

    function<bool(int)> dfs = [&](int u){
        vis[u] = 1;
        for(auto v : adj[u]){
            if(!vis[v]){
                if(dfs(v)) return true;
            } else if(vis[v] == 1){
                return true;
            }
        }
        vis[u] = 2;
        return false;
    };

    for(int i = 0; i < N; ++i){
        if(!vis[i] && dfs(i)) return true;
    }
    return false;
}

struct path_decomposition_tree{
    int N, timerHLD, num;
    vector<int> par, depth, sz, tin, tout, head;
    vector<vector<int>> adj;
    vector<pair<int, int>> edges;

    path_decomposition_tree(int N) :
         timerHLD(0), num(0), N(N), depth(N), sz(N), tin(N, -1), tout(N, -1), par(N), head(N), adj(N), edges() {}

    void add_edge(int u, int v){
        adj[u].emplace_back(v);
        adj[v].emplace_back(u);
    }

    void dfs_sz(int u){
        sz[u] = 1;
        for(auto& v : adj[u]){
            adj[v].erase(find(adj[v].begin(), adj[v].end(), u));
            depth[v] = depth[u] + 1;
            par[v] = u;
            dfs_sz(v);
            if(sz[adj[u][0]] < sz[v]) swap(adj[u][0], v);
            sz[u] += sz[v];
        }
    }

    void dfs_hld(int u, int hd){
        head[u] = hd;
        tin[u] = timerHLD++;
        for(auto v : adj[u]){
            if(v == adj[u][0]) dfs_hld(v, hd);
            else dfs_hld(v, v);
        }
        tout[u] = timerHLD - 1;
    }

    void build(int N){
        num = 2 * N;
        for(int i = N - 1; i > 0; --i){
            edges.emplace_back(i, i << 1);
            edges.emplace_back(i, i << 1 | 1);
        }
    }

    void preprocess(int rt){
        dfs_sz(rt);
        dfs_hld(rt, rt);
        assert(timerHLD == N);
        build(N);
    }

    int auxiliary_nodes(){ return num; }
    bool in_subtree(int u, int v){ return tin[u] <= tin[v] && tout[v] <= tout[u]; }

    void query_auxiliary_nodes(int l, int r, vector<int>& ans){
        l += N;
        r += N + 1;
        for(; l < r; l >>= 1, r >>= 1){
            if(l & 1) ans.emplace_back(l++);
            if(r & 1) ans.emplace_back(--r);
        }
    }

    vector<int> query(int u, int v){ //ignore u, v
        if(u == v) assert(false);
        vector<int> cur;

        if(tin[u] > tin[v]) swap(u, v);

        if(in_subtree(u, v)){
            v = par[v];
            while(head[u] != head[v]){
                if(depth[head[u]] < depth[head[v]]) swap(u, v);
                query_auxiliary_nodes(tin[head[u]], tin[u], cur);
                u = par[head[u]];
            }

            if(tin[u] > tin[v]) swap(u, v);
            if(tin[u] < tin[v]) query_auxiliary_nodes(tin[u] + 1, tin[v], cur);
            return cur;
        } else{
            u = par[u];
            v = par[v];
        }

        while(head[u] != head[v]){
            if(depth[head[u]] < depth[head[v]]) swap(u, v);
            query_auxiliary_nodes(tin[head[u]], tin[u], cur);
            u = par[head[u]];
        }

        if(tin[u] > tin[v]) swap(u, v);
        query_auxiliary_nodes(tin[u], tin[v], cur);
        return cur;
    }

    int get(int u){
        return tin[u] + N;
    }
};

void testcase(){
    int N;
    cin >> N;

    path_decomposition_tree tr(N);
    for(int i = 1; i < N; ++i){
        int u, v;
        cin >> u >> v;
        --u, --v;
        tr.add_edge(u, v);
    }

    int M;
    cin >> M;

    tr.preprocess(0);
    int offset = tr.auxiliary_nodes();
    int nodes = 2 * offset + M;
    vector<vector<int>> G(nodes);

    for(auto [u, v] : tr.edges){
        G[u].emplace_back(v); //for T
        G[v + offset].emplace_back(u + offset); //for S
    }

    for(int i = 0; i < M; ++i){
        int s, t;
        cin >> s >> t;

        --s, --t;
        int loc = 2 * offset + i;
        vector<int> compress_nodes = tr.query(s, t); //auxiliary nodes without s, t
        for(auto it : compress_nodes){
            G[loc].emplace_back(it);
            G[it + offset].emplace_back(loc);
        }

        int pS = tr.get(s);
        G[loc].emplace_back(pS + offset);
        G[loc].emplace_back(pS);

        int pT = tr.get(t);
        G[pT].emplace_back(loc);
        G[pT + offset].emplace_back(loc);
    }

    cout << (cycle_detection(G) ? "No\n" : "Yes\n");
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

#ifdef LOCAL
    freopen("task.inp", "r", stdin);
    freopen("task.out", "w", stdout);
#endif // LOCAL

    int T;
    cin >> T;
    while(T--) testcase();

    return 0;
}

Compilation message (stderr)

jail.cpp: In constructor 'path_decomposition_tree::path_decomposition_tree(int)':
jail.cpp:31:22: warning: 'path_decomposition_tree::num' will be initialized after [-Wreorder]
   31 |     int N, timerHLD, num;
      |                      ^~~
jail.cpp:31:9: warning:   'int path_decomposition_tree::N' [-Wreorder]
   31 |     int N, timerHLD, num;
      |         ^
jail.cpp:36:5: warning:   when initialized here [-Wreorder]
   36 |     path_decomposition_tree(int N) :
      |     ^~~~~~~~~~~~~~~~~~~~~~~
jail.cpp:32:38: warning: 'path_decomposition_tree::tout' will be initialized after [-Wreorder]
   32 |     vector<int> par, depth, sz, tin, tout, head;
      |                                      ^~~~
jail.cpp:32:17: warning:   'std::vector<int> path_decomposition_tree::par' [-Wreorder]
   32 |     vector<int> par, depth, sz, tin, tout, head;
      |                 ^~~
jail.cpp:36:5: warning:   when initialized here [-Wreorder]
   36 |     path_decomposition_tree(int N) :
      |     ^~~~~~~~~~~~~~~~~~~~~~~
jail.cpp: In function 'void testcase()':
jail.cpp:151:14: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  151 |     for(auto [u, v] : tr.edges){
      |              ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...