#include using namespace std; class Persistent_UnionFind { public: int nrComponents; explicit Persistent_UnionFind(){ } Persistent_UnionFind(const int n, const int nr_q) : nrComponents(0), Parent(vector(n + 1)), Size(vector(n + 1)), top(0), Stack(vector>(nr_q)) { for (int i = 1; i <= n; ++i) MakeSet(i); } void MakeSet(int x) { Parent[x] = x; Size[x] = 1; } int Find(int x) const { if (Parent[x] != x) return Find(Parent[x]); else return Parent[x]; } void Union(int x, int y) { x = Find(x); y = Find(y); pair operation = {-1, -1}; if (x != y) { if (Size[x] < Size[y]) swap(x, y); /// append y to x Size[x] += Size[y]; Parent[y] = x; nrComponents--; operation = {x, y}; ///x-root, y-son } Stack[top++] = operation; } void disconnect(int x, int y) /// disconned y from x { if (Parent[y] == x) { Parent[y] = y; Size[x] -= Size[y]; nrComponents++; } } void rollback() { top--; if (Stack[top].first != -1) disconnect(Stack[top].first, Stack[top].second); } bool connected(int x, int y) const { return Find(x) == Find(y); } int sizeComponent(int x) const { return Size[Find(x)]; } private: vector Parent; vector Size; int top; vector> Stack; }; const int buffer=1<<13; char buff[buffer]; int cnt=0; //getInt() reads and returns one integer at a time int getInt() { int number = 0; while(buff[cnt] < '0' || '9' < buff[cnt]) if(++cnt >= buffer) fread(buff, buffer, 1, stdin), cnt = 0; while('0' <= buff[cnt] && buff[cnt] <= '9') { number = number * 10 + buff[cnt] - '0'; if(++cnt >= buffer) fread(buff, buffer, 1, stdin), cnt = 0; } return number; } int main() { // freopen("data.in", "r", stdin); int N, M; N = getInt(); M = getInt(); Persistent_UnionFind PUF(N, M); while (M--) { int tip, x, y; tip = getInt(); if (tip == 1) { x = getInt(); y = getInt(); PUF.Union(x, y); } else if (tip == 2) { x = getInt(); while (x--) PUF.rollback(); } else { x = getInt(); y = getInt(); printf("%d\n", PUF.connected(x, y)); } } return 0; }