1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| #include <iostream> #include <vector> #include <tuple> #define maxn 100010 using namespace std;
int n, m, k, bl[maxn], t[maxn];
struct Edge { int to, next; } e[maxn]; int c1, head[maxn], du[maxn]; inline void add_edge(int u, int v) { e[c1].to = v; e[c1].next = head[u]; head[u] = c1++; }
int in[maxn], out[maxn]; void dfs(int u) { static int cnt = 0; in[u] = ++cnt; for (int i = head[u]; ~i; i = e[i].next) dfs(e[i].to); out[u] = cnt; }
int sz[maxn], fa[maxn], st[maxn], top; void init_fa(int n) { for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1; }
int find(int x) { return fa[x] == x ? x : find(fa[x]); }
inline void merge(int x, int y) { int fx = find(x), fy = find(y); if (sz[fx] < sz[fy]) swap(fx, fy); fa[fy] = fx; sz[fx] += sz[fy]; st[++top] = fy; }
inline void undo() { int x = st[top--]; sz[fa[x]] -= sz[x]; fa[x] = x; }
struct Query { int opt, x, y; } Q[maxn];
vector<tuple<int, int, int>> A[maxn];
int ans[maxn]; int main() { fill(head, head + maxn, -1); ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m; init_fa(n); for (int i = 1; i <= m; ++i) { int x, y; cin >> Q[i].opt >> x; if (Q[i].opt == 1) { cin >> y; ++du[x]; add_edge(y, x); merge(x, y); } else if (Q[i].opt == 2) ++k, bl[k] = x, t[k] = i; else cin >> y; Q[i].x = x; Q[i].y = y; } for (int i = 1; i <= n; ++i) if (!du[i]) dfs(i); for (int i = 1; i <= m; ++i) if (Q[i].opt == 3) { int x = Q[i].x, y = Q[i].y; if (in[x] <= in[bl[y]] && in[bl[y]] <= out[x]) A[t[y]].emplace_back(x, bl[y], i); else ans[i] = -1; } for (int i = m; i; --i) { if (Q[i].opt == 1) undo(); for (auto t : A[i]) { int x, y, k; tie(x, y, k) = t; ans[k] = find(x) == find(y) ? 1 : -1; } } for (int i = 1; i <= m; ++i) if (ans[i] == 1) cout << "YES\n"; else if (ans[i] == -1) cout << "NO\n"; return 0; }
|