#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
struct DisjointSetUnion
{
vector<int> root;
vector<int> size;
vector<int> vacant;
vector<vector<int>> G;
explicit DisjointSetUnion(int n) : root(vector<int>(n)), size(vector<int>(n)), vacant(vector<int>(n)), G(vector<vector<int>>(n))
{
for (int i = 0; i < n; ++i)
{
root[i] = i;
size[i] = 1;
}
}
int find(int v)
{
if (root[v] != v) root[v] = find(root[v]);
return root[v];
}
void join(int a, int b)
{
if (size[a] < size[b]) swap(a, b);
G[a].push_back(b);
root[b] = a;
size[a] += size[b];
vacant[a] += vacant[b];
}
void traverse(int v, bool flag, vector<int> &map, vector<int> &node, vector<bool> &status)
{
node[map[v]] = 0;
status[map[v]] = flag;
map[v] = 0;
for (int u : G[v]) traverse(u, flag, map, node, status);
}
void vacate(int v, vector<int> &map, vector<int> &node, vector<bool> &status)
{
++vacant[v];
if (size[v] > vacant[v] + 1) return;
traverse(v, false, map, node, status);
}
};
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
vector<int> node(n + 1);
vector<bool> status(n + 1);
vector<int> map(n + 2 * q + 1);
DisjointSetUnion U(n + 2 * q + 1);
int w = 1;
char op;
int a, b;
while (q--)
{
cin >> op >> a;
if (op == '+')
{
cin >> b;
if (status[a]) a = b;
if (status[b]) b = a;
if (!node[a])
{
node[a] = w;
map[w++] = a;
}
if (!node[b])
{
node[b] = w;
map[w++] = b;
}
int r = U.find(node[a]);
int s = U.find(node[b]);
if (r == s) U.traverse(r, true, map, node, status);
else U.join(r, s);
}
else if (op == '-')
{
if (node[a])
{
int r = U.find(node[a]);
U.vacate(r, map, node, status);
}
map[node[a]] = 0;
node[a] = 0;
status[a] = false;
}
else
{
if (status[a]) cout << '1';
else if (node[a]) cout << '?';
else cout << '0';
}
}
}
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <iostream> #include <string> #include <algorithm> #include <vector> using namespace std; struct DisjointSetUnion { vector<int> root; vector<int> size; vector<int> vacant; vector<vector<int>> G; explicit DisjointSetUnion(int n) : root(vector<int>(n)), size(vector<int>(n)), vacant(vector<int>(n)), G(vector<vector<int>>(n)) { for (int i = 0; i < n; ++i) { root[i] = i; size[i] = 1; } } int find(int v) { if (root[v] != v) root[v] = find(root[v]); return root[v]; } void join(int a, int b) { if (size[a] < size[b]) swap(a, b); G[a].push_back(b); root[b] = a; size[a] += size[b]; vacant[a] += vacant[b]; } void traverse(int v, bool flag, vector<int> &map, vector<int> &node, vector<bool> &status) { node[map[v]] = 0; status[map[v]] = flag; map[v] = 0; for (int u : G[v]) traverse(u, flag, map, node, status); } void vacate(int v, vector<int> &map, vector<int> &node, vector<bool> &status) { ++vacant[v]; if (size[v] > vacant[v] + 1) return; traverse(v, false, map, node, status); } }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, q; cin >> n >> q; vector<int> node(n + 1); vector<bool> status(n + 1); vector<int> map(n + 2 * q + 1); DisjointSetUnion U(n + 2 * q + 1); int w = 1; char op; int a, b; while (q--) { cin >> op >> a; if (op == '+') { cin >> b; if (status[a]) a = b; if (status[b]) b = a; if (!node[a]) { node[a] = w; map[w++] = a; } if (!node[b]) { node[b] = w; map[w++] = b; } int r = U.find(node[a]); int s = U.find(node[b]); if (r == s) U.traverse(r, true, map, node, status); else U.join(r, s); } else if (op == '-') { if (node[a]) { int r = U.find(node[a]); U.vacate(r, map, node, status); } map[node[a]] = 0; node[a] = 0; status[a] = false; } else { if (status[a]) cout << '1'; else if (node[a]) cout << '?'; else cout << '0'; } } } |
English