Untitled
unknown
c_cpp
10 months ago
2.8 kB
6
Indexable
#include <bits/stdc++.h> using namespace std; #define rep(i, from, to) for (int i = from; i < (to); ++i) #define trav(a, x) for (auto& a : x) #define all(x) x.begin(), x.end() #define sz(x) (int)(x).size() typedef long long ll; typedef pair<int, int> pii; typedef vector<int> vi; struct Edge { int u, v, id; }; struct UF { vi v, deg; vector<vector<Edge>> ed, ed2; UF(int n) : v(n, -1), deg(n), ed(n), ed2(n) {} int find(int x) { return v[x] < 0 ? x : v[x] = find(v[x]); } void join(int a, int b) { a = find(a), b = find(b); if (a == b) return; if (-v[a] < -v[b]) swap(a, b); v[a] += v[b]; deg[a] += deg[b]; ed[a].insert(ed[a].end(), all(ed[b])); ed2[a].insert(ed2[a].end(), all(ed2[b])); v[b] = a; } }; int main() { cin.sync_with_stdio(false); cin.exceptions(cin.failbit); int N; cin >> N; if (N == 1) { cout << 0 << endl; return 0; } UF uf(N); int u, v; set<pii> source, target; rep(i,0,N-1) { cin >> u >> v; if (u > v) swap(u, v); source.insert(pii(u,v)); } rep(i,0,N-1) { cin >> u >> v; if (u > v) swap(u, v); if (source.count(pii(u,v))) { uf.join(u, v); source.erase(pii(u,v)); } else target.insert(pii(u,v)); } int delta = sz(source); assert(delta == sz(target)); vector<bool> dead; int eid = 0; trav(e, source) { tie(u,v) = e; Edge edg = {u, v, eid++}; uf.ed[uf.find(u)].push_back(edg); uf.ed[uf.find(v)].push_back(edg); dead.push_back(false); } trav(e, target) { tie(u,v) = e; Edge edg = {u, v, eid++}; uf.ed2[uf.find(u)].push_back(edg); uf.ed2[uf.find(v)].push_back(edg); dead.push_back(false); } vi leaves; rep(i,0,N) { uf.deg[i] = sz(uf.ed[i]); if (uf.deg[i] == 1) leaves.push_back(i); } vector<tuple<int, int, int, int>> out; while (!leaves.empty()) { int theLeaf = leaves.back(); int comp = uf.find(theLeaf); leaves.pop_back(); if (uf.ed[comp].empty()) continue; Edge e = uf.ed[comp].back(), e2; uf.ed[comp].pop_back(); if (dead[e.id]) { leaves.push_back(theLeaf); continue; } int x = e.u, y = e.v; if (uf.find(x) != comp) swap(x, y); assert(uf.find(x) == comp); for (;;) { assert(uf.ed2[comp].size() >= 1); e2 = uf.ed2[comp].back(); uf.ed2[comp].pop_back(); if (!dead[e2.id]) break; } int x2 = e2.u, y2 = e2.v; if (uf.find(x2) != comp) swap(x2, y2); assert(uf.find(x2) == comp); out.emplace_back(x, y, x2, y2); dead[e.id] = true; dead[e2.id] = true; --uf.deg[comp]; if (--uf.deg[uf.find(y)] == 1) { leaves.push_back(y); } uf.join(x, y2); } cout << sz(out) << endl; trav(t, out) { int a,b,c,d; tie(a,b,c,d) = t; cout << a << ' ' << b << ' ' << c << ' ' << d << '\n'; } assert(sz(out) == delta); }
Editor is loading...
Leave a Comment