1814. 边双连通分量

模板题。

#include <bits/stdc++.h> using namespace std; #define sc(x) scanf("%lld", &x) typedef long long ll; const ll mn = 1e5 + 10; ll n, m, hd[mn], cnt, w[mn]; struct edge { ll to, nx, w, idx, isbridge = false; } e[mn * 2]; ll st, dfn[mn], low[mn], dcnt, vis[mn]; vector<ll> dcc[mn]; //边双 ll order[mn]; signed main() { sc(n), sc(m); auto adde = [&](ll u, ll v, ll w, ll idx) { e[++cnt] = {v, hd[u], w, idx}; hd[u] = cnt; ::w[idx] = w; }; for (ll i = 1, u, v, w; i <= m; ++i) { sc(u), sc(v), sc(w), adde(u, v, w, i), adde(v, u, w, i); } auto tarjan = [&](auto self, ll u, ll fa) -> void { dfn[u] = low[u] = ++st; for (ll i = hd[u]; i; i = e[i].nx) { ll v = e[i].to, idx = e[i].idx; if (!dfn[v]) { self(self, v, u); low[u] = min(low[u], low[v]); if (dfn[u] < low[v]) { e[idx].isbridge = true; } } else if (v != fa) { low[u] = min(low[u], dfn[v]); } } }; tarjan(tarjan, 1, 0); auto dfs = [&](auto self, ll u) -> void { vis[u] = true; for (ll i = hd[u]; i; i = e[i].nx) { ll v = e[i].to, idx = e[i].idx; if (!e[idx].isbridge) { dcc[dcnt].push_back(idx); if (!vis[v]) { self(self, v); } } } }; for (ll i = 1; i <= n; ++i) { if (!vis[i]) { ++dcnt; dfs(dfs, i); } } printf("%lld\n", dcnt); for (ll i = 1; i <= dcnt; ++i) { sort(dcc[i].begin(), dcc[i].end()); dcc[i].erase(unique(dcc[i].begin(), dcc[i].end()), dcc[i].end()); sort(dcc[i].begin(), dcc[i].end(), [&](ll u, ll v) { return w[u] < w[v]; }); if (dcc[i].size() == 0) dcc[i].push_back(mn - 1); } w[mn - 1] = -2e9; for (ll i = 1; i <= dcnt; ++i) { order[i] = i; } sort(order + 1, order + 1 + dcnt, [&](ll u, ll v) { return w[dcc[u].front()] < w[dcc[v].front()]; }); for (ll i = 1; i <= dcnt; ++i) { if (dcc[order[i]].front() == mn - 1) { printf("0\n"); continue; } printf("%lld ", dcc[order[i]].size()); for (auto j : dcc[order[i]]) { printf("%lld ", w[j]); } printf("\n"); } return 0; }