Submission #1187562

#TimeUsernameProblemLanguageResultExecution timeMemory
1187562browntoadJail (JOI22_jail)C++20
0 / 100
117 ms175940 KiB
#include <bits/stdc++.h>
using namespace std;
#define ll long long
// #define int ll
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define REP(i, n) FOR(i, 0, n) 
#define REP1(i, n) FOR(i, 1, n+1)
#define RREP(i, n) for (int i = (n)-1; i >= 0; i--)
#define pii pair<int, int>
#define f first
#define s second
#define pb push_back
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) (int)((x).size())
#define endl '\n'
#define IOS() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)

const ll maxn = 120005;
const ll mod = 1e9+7;
const ll inf = 1ll<<60;
const int mxpw = 18;
const ll totti = maxn + 2 * (mxpw+1) * maxn + 4 * maxn;

ll pw(ll a, ll p){
    ll rt = 1;
    while(p > 0){
        if (p & 1){
            rt *= a;
            rt %= mod;
        }
        a *= a;
        a %= mod;
        p >>= 1;
    }
    return rt;
}
ll inv(int a){
    return pw(a, mod-2);
}

int n1, n2;
vector<int> g[maxn], g2[totti];
vector<pii> qqs; 
vector<pii> euler(maxn);

vector<int> itselfS(maxn), itselfT(maxn); 
int cid = 0;

vector<int> in(totti), occ(totti), dep(maxn);

int up[maxn][mxpw];
int forS[maxn][mxpw], forT[maxn][mxpw];
bool ispar(int p, int u){
    return euler[p].f <= euler[u].f && euler[u].s <= euler[p].s;
}

int cval = 0;
int lca(int a, int b){
    if (dep[a] < dep[b]) swap(a, b);
    int tmp = dep[a] - dep[b];
    REP(i, mxpw){
        if ((1<<i)&tmp) a = up[a][i];
    }
    if (a == b) return a;
    RREP(i, mxpw){
        if (up[a][i] != up[b][i]){
            a = up[a][i];
            b = up[b][i];
        }
    }
    return up[a][0];
}
bool check(int a, int b, int tst){
    int lab = lca(a, b);
    //cout<<a<<' '<<b<<' '<<lab<<endl;
    if (!ispar(lab, tst)) return 0;
    return ispar(tst, a) || ispar(tst, b);
}

//int DEBUG = 0;

void add_edge(int u, int v){
    g2[u].pb(v);
    in[v]++;
    //DEBUG++;
    //cout<<u<<" - "<<v<<endl;
}
void dfs(int u, int pre){
    itselfS[u] = cid++;
    itselfT[u] = cid++;
    euler[u].f = cval++;
    up[u][0] = max(pre, 1);
    REP1(i, mxpw-1) up[u][i] = up[up[u][i-1]][i-1];
    REP(i, mxpw){
        if (i == 0){
            add_edge(itselfS[u], cid);
            add_edge(itselfS[up[u][0]], cid);
        }
        else{
            add_edge(forS[u][i-1], cid);
            add_edge(forS[up[u][i]][i-1], cid);
        }

        forS[u][i] = cid++; // actually, it includes 2^(0+1) nodes
    }
    REP(i, mxpw){
        if (i == 0){
            add_edge(cid, itselfT[u]);
            add_edge(cid, itselfT[up[u][0]]);
        }
        else{
            add_edge(cid, forT[u][i-1]);
            add_edge(cid, forT[up[i][i]][i-1]);
        }

        forT[u][i] = cid++; // actually, it includes 2^(0+1) nodes
    }


    for (auto v:g[u]){
        if (v == pre) continue;
        dep[v] = dep[u]+1;
        dfs(v, u);
    }
    euler[u].s = cval++;
}

vector<int> Sbwoah[maxn], Tbwoah[maxn];
vector<int> lrT(maxn), rlT(maxn), lrS(maxn), rlS(maxn); // query id -> big graph id
vector<int> headT(maxn), headS(maxn);

void init(){
    cin>>n1;
    REP1(i, n1) {
        g[i].clear();
        Sbwoah[i].clear();
        Tbwoah[i].clear();
        euler[i] = {-1, -1};
    }
    REP(i, n1-1){
        int u, v; cin>>u>>v;
        g[u].pb(v); g[v].pb(u);
    }
    cin>>n2;
    qqs.clear();
    REP(i, n2){
        int a, b; cin>>a>>b;
        Sbwoah[a].pb(i);
        Tbwoah[b].pb(i);
        qqs.pb({a, b});
    }
    REP1(i, n1) sort(ALL(Sbwoah[i]));
    REP1(i, n1) sort(ALL(Tbwoah[i]));
    cid = n2;
    cval = 1;

    int ctoti = 4*n2 + 2 * (mxpw+1) * n1 + n2;
    REP(i, ctoti){
        g2[i].clear();
        in[i] = 0;
        occ[i] = 0;
    }

}
void special(int u, int id){
    if (SZ(Sbwoah[u])){
        int pid = lower_bound(ALL(Sbwoah[u]), id)-Sbwoah[u].begin();
        if (pid >= SZ(Sbwoah[u]) || Sbwoah[u][pid] != id){
            add_edge(headS[u], id);
        }
        else{
            if (pid > 0) add_edge(lrS[Sbwoah[u][pid-1]], id);
            if (pid < SZ(Sbwoah[u])-1) add_edge(rlS[Sbwoah[u][pid+1]], id);
        }
    }
    if (SZ(Tbwoah[u])){
        int pid = lower_bound(ALL(Tbwoah[u]), id)-Tbwoah[u].begin();
        if (pid >= SZ(Tbwoah[u]) || Tbwoah[u][pid] != id){
            add_edge(id, headT[u]);
        }
        else{
            if (pid > 0) add_edge(id, rlT[Tbwoah[u][pid-1]]);
            if (pid < SZ(Tbwoah[u])-1) add_edge(id, lrT[Tbwoah[u][pid+1]]);
        }
    }
}
signed main(){
    IOS();
    int Q; cin>>Q;
    while(Q--){
        init();
        dfs(1, -1);

        /*REP(i, n2){
            REP(j, n2){
                if (i == j) continue;
                if (check(qqs[i].f, qqs[i].s, qqs[j].f)){
                    g2[j].pb(i);
                    //cout<<j<<'e'<<i<<endl;
                    in[i]++;
                }
                if (check(qqs[i].f, qqs[i].s, qqs[j].s)){
                    g2[i].pb(j);
                    in[j]++;
                    //cout<<i<<'e'<<j<<endl;
                }
            }
        }
        
        REP1(i, n1){
            cout<<itselfS[i]<<' ';
            REP(j, mxpw) cout<<forS[i][j]<<' ';
            cout<<endl;
        }
        cout<<endl;
        REP1(i, n1){
            cout<<itselfT[i]<<endl;
            REP(j, mxpw) cout<<forT[i][j]<<' ';
            cout<<endl;
        }
        cout<<endl;
        */
        
        REP1(i, n1){
            int plee = -1;
            REP(j, SZ(Sbwoah[i])){
                if (plee != -1) add_edge(plee, cid);
                add_edge(Sbwoah[i][j], cid);
                lrS[Sbwoah[i][j]] = cid;
                if (j == SZ(Sbwoah[i])-1) headS[i] = cid;
                plee = cid++;
            }
            plee = -1;
            RREP(j, SZ(Sbwoah[i])){
                if (plee != -1) add_edge(plee, cid);
                add_edge(Sbwoah[i][j], cid);
                rlS[Sbwoah[i][j]] = cid;
                plee = cid++;
            }

            plee = -1;
            REP(j, SZ(Tbwoah[i])){
                if (plee != -1) add_edge(plee, cid);
                else headT[i] = cid;
                add_edge(cid, Tbwoah[i][j]);
                lrT[Tbwoah[i][j]] = cid;
                plee = cid++;
            }
            plee = -1;
            RREP(j, SZ(Tbwoah[i])){
                if (plee != -1) add_edge(plee, cid);
                add_edge(cid, Tbwoah[i][j]);
                rlT[Tbwoah[i][j]] = cid;
                plee = cid++;
            }
        }
        
        REP(i, n2){
            add_edge(i, itselfS[qqs[i].f]);
            add_edge(itselfT[qqs[i].s], i);
        }
        

        //cout<<DEBUG<<endl;
        REP(i, n2){
            int lcc = lca(qqs[i].f, qqs[i].s);
            special(qqs[i].f, i);
            special(qqs[i].s, i);
            if (lcc == qqs[i].f){
                int cur = up[qqs[i].s][0], expdis = -dep[lcc] + dep[qqs[i].s] - 1;
                REP(b, mxpw){
                    if ((1<<b)&expdis){
                        if (b == 0) add_edge(itselfS[cur], i);
                        else add_edge(forS[cur][b-1], i);
                        if (b == 0) add_edge(i, itselfT[cur]);
                        else add_edge(i, forT[cur][b-1]);
                        cur = up[cur][b];
                    }
                }
            }
            else if (lcc == qqs[i].s){
                int cur = up[qqs[i].f][0], expdis = -dep[lcc] + dep[qqs[i].f] - 1;
                REP(b, mxpw){
                    if ((1<<b)&expdis){
                        if (b == 0) add_edge(itselfS[cur], i);
                        else add_edge(forS[cur][b-1], i);
                        if (b == 0) add_edge(i, itselfT[cur]);
                        else add_edge(i, forT[cur][b-1]);
                        cur = up[cur][b];
                    }
                }
            }
            else{
                int cur = up[qqs[i].f][0], expdis = -dep[lcc] + dep[qqs[i].f];
                REP(b, mxpw){
                    if ((1<<b)&expdis){
                        if (b == 0) add_edge(itselfS[cur], i);
                        else add_edge(forS[cur][b-1], i);
                        if (b == 0) add_edge(i, itselfT[cur]);
                        else add_edge(i, forT[cur][b-1]);
                        cur = up[cur][b];
                    }
                }
                cur = up[qqs[i].s][0]; expdis = -dep[lcc] + dep[qqs[i].s]-1;
                REP(b, mxpw){
                    if ((1<<b)&expdis){
                        if (b == 0) add_edge(itselfS[cur], i);
                        else add_edge(forS[cur][b-1], i);
                        if (b == 0) add_edge(i, itselfT[cur]);
                        else add_edge(i, forT[cur][b-1]);
                        cur = up[cur][b];
                    }
                }
            }
            
            
        }
        //cout<<DEBUG<<endl;

        queue<int> qu;
        REP(i, cid){
            if (in[i] == 0){
                qu.push(i);
            }
        }
        while(SZ(qu)){
            int tp = qu.front(); qu.pop();
            occ[tp] = 1;
            for (auto v:g2[tp]){
                in[v]--;
                if (in[v] == 0) qu.push(v);
            }
        }

        /*REP(i, cid){
            cout<<i<<'+'<<endl;
            for (auto y:g2[i]) cout<<y<<' ';
            cout<<endl;
        }
        */
        

        bool ex = 0;
        REP(i, cid) if (occ[i] == 0) {
            ex = 1;
            //cout<<'p'<<i<<endl;
        }
        
        cout<<(ex?"No":"Yes")<<endl;
    }

}
/*
1
7
1 2
2 3
3 4
4 5
3 6
6 7
2
4 1
5 7

1
4
1 2
2 3
3 4
1
4 1


1
4
1 2
1 3
1 4
3
2 3
3 4
4 2
*/
#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...