voidadd(int u, int v){ E[u].push_back({ v, int(edge.size()) }); E[v].push_back({ u, int(edge.size()) }); edge.push_back({ u, v }); }
voiddfs(int u){ low[u] = dfn[u] = unix++; for (auto& [v, id] : E[u]) { if (vis[id]) continue; vis[id] = 1; stk.push_back(id); if (dfn[v] == -1) { dfs(v); low[u] = min(low[u], low[v]); if (low[v] >= dfn[u]) { int jd; do { jd = stk.back(); bel[jd] = tot; stk.pop_back(); } while (jd != id); tot++; } } else { low[u] = min(low[u], dfn[v]); } } }
structGraph { int n; set<int> cut; // 割点 vector<set<int>> vertex; vector<vector<int>> edge; Graph(int n) : n(n), vertex(n), edge(n) {} }; Graph work(){ bel.assign(edge.size(), -1); vis.resize(edge.size()); for (int u = 0; u < n; u++) { if (dfn[u] == -1) dfs(u); }
for (int i = 0; i < edge.size(); ++i) { auto [u, v] = edge[i]; if (u == v) continue; cnt[u].insert(bel[i]); cnt[v].insert(bel[i]); } for (int u = 0; u < n; u++) { if (cnt[u].empty()) { cnt[u].insert(++tot); } }
Graph G(tot); for (int i = 0; i < edge.size(); ++i) { auto [u, v] = edge[i]; if (u == v) continue; G.edge[bel[i]].push_back(i); G.vertex[bel[i]].insert(u); G.vertex[bel[i]].insert(v); } for (int u = 0; u < n; u++) { if (cnt[u].size() >= 2) { G.cut.insert(u); } } return G; } };
auto G = vbcc.work(); vector<int> res; for (int i = 0; i < G.n; i++) { if (G.vertex[i].size() == G.edge[i].size()) { for (auto& j : G.edge[i]) res.push_back(j); } } sort(res.begin(), res.end()); cout << res.size() << "\n"; for (auto& x : res) { cout << ++x << " "; }
例 3 已知一个图,请问判断这个图是否是v-flower。v−flower 定义:中间是一个v 边简单环,而这个环上的每一个点为一个v 边简单环上的一个点。(2439, CF1811F. Is It Flower?)
每个双联通分量都是大小为n 的简单环,且某个双联通分量的每个点都是割点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
auto G = vbcc.work(); bool good = false; for (int i = 0; i < G.n; i++) { bool centre = true; for (auto u : G.vertex[i]) { if (!G.cut.count(u)) centre = false; } good |= centre; } for (int i = 0; i < G.n; i++) { if (G.edge[i].size() != G.vertex[i].size() || G.vertex[i].size() + 1 != G.n) good = false; // WA } cout << (good ? "YES" : "NO") << "\n";