# 2022牛客多校第8场 I.Equivalence in Connectivity

## Code

#include <bits/stdc++.h>
using namespace std;

#define LL long long

const int maxn = 100005;

struct Graph {
struct edge { int Next, to; };
edge G[200010];
int cnt;

Graph() :cnt(2) {}
void clear(int n) {
}
void add_edge(int u, int v) {
G[cnt].to = v;
}
};

struct UFS {
int f[maxn], rk[maxn];
pair<LL, LL> val[maxn];
stack<pair<int, int>> opt;
pair<LL, LL> hashval;
int find(int u) {
while (u ^ f[u]) u = f[u];
return u;
}
void merge(int u, int v) {
if ((u = find(u)) == (v = find(v))) return;
if (rk[u] > rk[v]) swap(u, v);
opt.push(make_pair(u, rk[u] == rk[v]));
f[u] = v; rk[v] += (rk[u] == rk[v]);
hashval.first -= val[u].first + val[v].first;
hashval.second -= val[u].second + val[v].second;
val[v].first ^= val[u].first;
val[v].second ^= val[u].second;
hashval.first += val[v].first;
hashval.second += val[v].second;
}
void undo() {
int u = opt.top().first, v = f[u];
rk[v] -= opt.top().second;
hashval.first -= val[v].first;
hashval.second -= val[v].second;
val[v].first ^= val[u].first;
val[v].second ^= val[u].second;
hashval.first += val[u].first + val[v].first;
hashval.second += val[u].second + val[v].second;
f[u] = u; opt.pop();
}
};

UFS S;
Graph G;
map<pair<int, int>, int> mp;
pair<int, int> edges[maxn << 1];
set<pair<int, int>> s[maxn << 1];
vector <pair<int, int>> T[maxn << 2];
struct opt { int o, u, v; }opts[maxn];
int dfn[maxn], dfn_t[maxn], sz[maxn];
int t, k, n, m, dfn_index;

void DFS(int u, int fa) {
dfn[u] = ++dfn_index;
dfn_t[dfn[u]] = u;
sz[u] = 1;
for (int i = G.head[u];i;i = G.G[i].Next) {
int v = G.G[i].to;
if (v == fa) continue;;
DFS(v, u);
sz[u] += sz[v];
}
}

void build(int rt, int L, int R) {
T[rt].clear();
if (L == R) return;
int mid = (L + R) >> 1;
build(rt << 1, L, mid);
build(rt << 1 | 1, mid + 1, R);
}

void insert(int rt, int L, int R, int QL, int QR, pair<int, int> x) {
if (R < QL || QR < L) return;
if (QL <= L && R <= QR) { T[rt].push_back(x); return; }
int mid = (L + R) >> 1;
insert(rt << 1, L, mid, QL, QR, x);
insert(rt << 1 | 1, mid + 1, R, QL, QR, x);
}

pair<LL, LL> hashval[maxn];
pair<LL, LL> val[maxn];

void DFS(int rt, int L, int R) {
int sz = S.opt.size();
pair<LL, LL> curval = S.hashval;
for (auto x : T[rt])
S.merge(x.first, x.second);
if (L == R) {
hashval[dfn_t[L]] = S.hashval;
while (S.opt.size() != sz) S.undo();
return;
}
int mid = (L + R) >> 1;
DFS(rt << 1, L, mid);
DFS(rt << 1 | 1, mid + 1, R);
while (S.opt.size() != sz) S.undo();
}

vector<int> group[maxn];
map<pair<LL, LL>, int> mp2;

void get_ans() {
int idx = 0; mp2.clear();
for (int i = 1;i <= k;++i) {
int id = 0;
if (!mp2.count(hashval[i])) { mp2[hashval[i]] = ++idx; id = idx; group[idx].clear(); }
else id = mp2[hashval[i]];
group[id].push_back(i);
}
printf("%d\n", idx);
for (int i = 1;i <= idx;++i) {
printf("%d", group[i].size());
for (auto x : group[i])
printf(" %d", x);
printf("\n");
}
}

int main() {
mt19937 gen(chrono::system_clock::now().time_since_epoch().count());
uniform_int_distribution<LL> dis(1, 1e9);
for (int i = 1;i <= 100000;++i)
val[i] = make_pair(dis(gen), dis(gen));
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &k, &n, &m);
mp.clear(); G.clear(k);

dfn_index = 0;
int index = 0;
S.hashval = make_pair(0LL, 0LL);
for (int i = 1;i <= n;++i) {
S.f[i] = i;
S.rk[i] = 0;
S.val[i] = val[i];
S.hashval.first += val[i].first;
S.hashval.second += val[i].second;
}
while (!S.opt.empty()) S.opt.pop();
for (int i = 1;i <= m;++i) {
int u, v;
scanf("%d%d", &u, &v);
if (u > v) swap(u, v);
mp[make_pair(u, v)] = ++index;
edges[index].first = u;
edges[index].second = v;
s[index].clear();
s[index].insert(make_pair(1, k));
}
char buf[10];
for (int i = 2;i <= k;++i) {
int p, u, v;
scanf("%d%s%d%d", &p, buf, &u, &v);
if (u > v) swap(u, v);
if (buf[0] == 'a') opts[i].o = 1;
else opts[i].o = 0;
opts[i].u = u; opts[i].v = v;
}
DFS(1, 0);
for (int i = 2;i <= k;++i) {
int u = opts[i].u, v = opts[i].v;
int id = 0;
if (mp.count(make_pair(u, v))) id = mp[make_pair(u, v)];
else {
mp[make_pair(u, v)] = id = ++index; s[index].clear();
edges[index].first = u;
edges[index].second = v;
}
s[id].insert(make_pair(dfn[i], dfn[i] + sz[i] - 1));
}
else { // remove
auto it = s[id].lower_bound(make_pair(dfn[i], maxn)); --it;
int l = it->first, r = it->second;
s[id].erase(it);
if (l <= dfn[i] - 1) s[id].insert(make_pair(l, dfn[i] - 1));
if (dfn[i] + sz[i] <= r) s[id].insert(make_pair(dfn[i] + sz[i], r));
}
}
build(1, 1, k);
for (int i = 1;i <= index;++i)
for (auto x : s[i])
insert(1, 1, k, x.first, x.second, edges[i]);
DFS(1, 1, k);
get_ans();
}
return 0;
}

posted @ 2022-08-30 19:41  AE酱  阅读(18)  评论(0编辑  收藏  举报