이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
#ifdef MIKU
string dbmc = "\033[1;38;2;57;197;187m", dbrs = "\033[0m";
#define debug(x...) cout << dbmc << "[" << #x << "]: ", dout(x)
void dout() { cout << dbrs << endl; }
template <typename T, typename ...U>
void dout(T t, U ...u) { cout << t << (sizeof...(u) ? ", " : ""); dout(u...); }
#else
#define debug(...) 39
#endif
// #define int long long
#define fs first
#define sc second
#define mp make_pair
#define FOR(i, j, k) for (int i = j, Z = k; i < Z; i++)
typedef pair<int, int> pii;
const int MXN = 120005, LG = 17;
int n, m, s[MXN], t[MXN];
enum ID_PREF {
NUM_ID = 0,
S_TREE_ID = 1,
T_TREE_ID = LG + 1
};
int f(int x, int y) {
return x * MXN + y;
}
namespace GRAPH {
vector<pii> edge;
int lst[MXN * (2 * LG + 1)];
int dfn[MXN * (2 * LG + 1)], low[MXN * (2 * LG + 1)], scc[MXN * (2 * LG + 1)], C, nc;
vector<int> st;
void init() {
FOR(i, 0, 2 * LG + 1) {
FOR(j, 1, n + 1) {
lst[f(i, j)] = -1;
}
}
}
void add_edge(int x, int y, bool rev = false) {
if (rev) swap(x, y);
// debug(x, y);
edge.push_back(mp(y, lst[x]));
lst[x] = edge.size() - 1;
}
void DFS(int id) {
C++;
dfn[id] = C;
low[id] = C;
st.push_back(id);
if (lst[id] != -1) {
for (pii now = edge[lst[id]]; true; now = edge[now.sc]) {
int i = now.fs;
if (scc[i]) {
if (now.sc == -1) break;
continue;
}
if (dfn[i]) {
low[id] = min(low[id], dfn[i]);
} else {
DFS(i);
low[id] = min(low[id], low[i]);
}
if (now.sc == -1) break;
}
}
if (low[id] == dfn[id]) {
int x;
nc++;
do {
x = st.back();
st.pop_back();
scc[x] = nc;
} while (x != id);
}
}
void SCC() {
FOR(pi, 0, 2 * LG + 1) FOR(i, 1, n + 1) {
int id = f(pi, i);
if (dfn[id]) continue;
DFS(id);
}
}
bool check() {
// debug();
// FOR(i, 1, m + 1) cout << scc[i] << ' ';
// cout << endl;
// debug();
sort(scc + 1, scc + m + 1);
FOR(i, 1, m) if (scc[i] == scc[i + 1]) return false;
return true;
}
void RESET() {
edge.clear();
C = 0;
nc = 0;
FOR(i, 0, 2 * LG + 1) {
FOR(j, 1, n + 1) {
int id = f(i, j);
dfn[id] = 0;
low[id] = 0;
scc[id] = 0;
}
}
}
}
namespace TREE {
vector<int> edge[MXN];
int p[LG][MXN], d[MXN];
void push_edge(int x, int y) {
edge[x].push_back(y);
edge[y].push_back(x);
}
void DFS(int id, int par, int dep) {
p[0][id] = par;
d[id] = dep;
for (auto &i : edge[id]) {
if (i == par) continue;
DFS(i, id, dep + 1);
}
}
void build_p() {
DFS(1, 1, 0);
FOR(i, 0, LG - 1) {
FOR(j, 1, n + 1) {
p[i + 1][j] = p[i][p[i][j]];
}
}
}
int leap_bin(int x, int w, vector<pii> &vnd) {
vnd.push_back(mp(w, x));
return p[w][x];
}
int leap(int x, int k, vector<pii> &vnd) {
// debug(x, k);
for (int w = LG - 1; w >= 0; w--) {
if (k & (1 << w)) {
x = leap_bin(x, w, vnd);
}
}
// debug(x);
return x;
}
vector<pii> LCA(int x, int y) {
vector<pii> vnd;
if (d[x] < d[y]) swap(x, y);
x = leap(x, d[x] - d[y], vnd);
// debug(x, y, d[x], d[y]);
if (x == y) {
vnd.push_back(mp(0LL, x));
return vnd;
}
for (int w = LG - 1; w >= 0; w--) {
if (p[w][x] == p[w][y]) continue;
x = leap_bin(x, w, vnd);
y = leap_bin(y, w, vnd);
}
vnd.push_back(mp(1LL, x));
vnd.push_back(mp(1LL, y));
return vnd;
}
void RESET() {
FOR(i, 1, n + 1) {
edge[i].clear();
d[i] = 0;
}
FOR(i, 0, LG) fill(p[i] + 1, p[i] + n + 1, 0);
}
}
struct TREE_AGENT {
int sr;
bool rev;
void init(int _sr, bool _rev) {
sr = _sr;
rev = _rev;
}
void connect() {
FOR(w, 0, LG - 1) {
FOR(i, 1, n + 1) {
GRAPH::add_edge(f(sr + w + 1, i), f(sr + w, i), rev);
GRAPH::add_edge(f(sr + w + 1, i), f(sr + w, TREE::p[w][i]), rev);
}
}
}
void add_edge(int x, vector<pii> vnd) {
for (auto &i : vnd) {
GRAPH::add_edge(x, f(i.fs + sr, i.sc), rev);
}
}
} sa, ta;
bool miku() {
int x, y;
cin >> n;
GRAPH::init();
FOR(i, 1, n) {
cin >> x >> y;
TREE::push_edge(x, y);
}
TREE::build_p();
sa.init(ID_PREF::S_TREE_ID, 1);
ta.init(ID_PREF::T_TREE_ID, 0);
sa.connect();
ta.connect();
cin >> m;
FOR(i, 1, m + 1) {
cin >> s[i] >> t[i];
GRAPH::add_edge(f(ID_PREF::NUM_ID, i), f(ID_PREF::S_TREE_ID, s[i]));
GRAPH::add_edge(f(ID_PREF::T_TREE_ID, t[i]), f(ID_PREF::NUM_ID, i));
vector<pii> vnd = TREE::LCA(s[i], t[i]);
// for (auto &i : vnd) {
// cout << i.fs << ' ' << i.sc << endl;
// }
// cout << endl;
sa.add_edge(i, vnd);
ta.add_edge(i, vnd);
}
GRAPH::SCC();
return GRAPH::check();
}
void RESET() {
GRAPH::RESET();
TREE::RESET();
}
int32_t main() {
cin.tie(0) -> sync_with_stdio(false);
cin.exceptions(cin.failbit);
int t;
cin >> t;
while (t--) {
cout << (miku() ? "Yes" : "No") << '\n';
RESET();
}
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |