题解:P15961 [ICPC 2018 Jakarta R] Boomerangs
这真是紫题吗,\(5\text{ min}\) 击杀了。
对每个连通块分别做,猜测一个连通块的答案为 \(\lfloor m/2\rfloor\)。
建出一棵 DFS 生成树,自底向上做。对于当前点 \(u\),将 \(u\) 未匹配的邻边两两配对,若有奇数条邻边则把 \((u,fa_u)\) 剩下来。这样只会在根节点处有 \(m\bmod{2}\) 条边无法匹配。于是我们就得到了构造。
随便实现就是 \(\mathcal{O}(n+m)\) 的了。
代码
#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
const int N = 1e5 + 5;
int n, m;
bool visP[N], visE[N];
pii E[N];
vector<pii> T[N];
vector<tuple<int, int, int>> ans;
void dfs(int x, int fx) {
visP[x] = 1;
for (auto [y, id] : T[x]) if (!visP[y]) dfs(y, x);
vector<int> edges;
int faId = 0;
for (auto [y, id] : T[x]) {
if (visE[id]) continue;
if (y == fx) faId = id;
else edges.emplace_back(id);
}
if (faId) edges.emplace_back(faId);
for (int i = 0; i + 1 < edges.size(); i += 2) {
int e1 = edges[i], e2 = edges[i + 1];
visE[e1] = visE[e2] = 1;
auto [u1, v1] = E[e1];
auto [u2, v2] = E[e2];
int y = u1 == x ? v1 : u1, z = u2 == x ? v2 : u2;
ans.emplace_back(y, x, z);
}
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m;
for (int i = 1, u, v; i <= m; ++i) {
cin >> u >> v;
T[u].emplace_back(v, i), T[v].emplace_back(u, i);
E[i] = {u, v};
}
for (int i = 1; i <= n; ++i) if (!visP[i]) dfs(i, 0);
cout << ans.size() << '\n';
for (auto [u, v, w] : ans) cout << u << ' ' << v << ' ' << w << '\n';
return 0;
}

浙公网安备 33010602011771号