QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#586811 | #906. 强连通分量 | xorzj | WA | 0ms | 3616kb | C++17 | 4.7kb | 2024-09-24 15:43:19 | 2024-09-24 15:43:20 |
Judging History
answer
#include <bits/stdc++.h>
#define rep(a, b, c) for (int a = b; a <= c; a++)
#define ALL(x) (x).begin(), (x).end()
#define IOS cin.tie(0)->sync_with_stdio(false)
#ifdef LOCAL
#include "debug.h"
#else
#define deb(...) 42
#endif
#define OPENSTACK
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MAXN = 2e5 + 5;
const int INF = 0x3f3f3f3f;
vector<pii>E;
// 如果原图都为边双分量,将其改为强联通分量时边的方向
struct EBCC {
int n;
vector<vector<pii>>& adj;
//到达的点 边的编号
vector<int> stk;
vector<int> dfn, low, bel;
vector<vector<int>> ebcc;
int m;
vector<int>bridge;
int cur;
EBCC(int n_, int m_, auto& adj_) : adj(adj_), n(n_), m(m_) { init(n, m); }
void init(int n, int m)
{
this->n = n;
this->m = m;
dfn.resize(n + 1);
low.resize(n + 1);
bel.assign(n + 1, -1);
bridge.resize(m * 2);
stk.clear();
cur = 0;
work();
}
void dfs(int x, int pre)
{
dfn[x] = low[x] = ++cur;
stk.push_back(x);
for (auto [y, id] : adj[x]) {
if (dfn[y] == 0) {
E.emplace_back(x, y);
dfs(y, id);
low[x] = min(low[x], low[y]);
if (low[y] > dfn[x]) {
bridge[id] = bridge[id ^ 1] = 1;
}
}
else if (id != (pre ^ 1)) {
if (dfn[y] < dfn[x])E.emplace_back(x, y);
low[x] = min(low[x], dfn[y]);
}
}
if (dfn[x] == low[x]) {
int cnt = ebcc.size();
ebcc.push_back({});
int y;
do {
y = stk.back();
bel[y] = cnt;
stk.pop_back();
ebcc.back().push_back(y);
} while (y != x);
}
}
void work()
{
for (int i = 1; i <= n; i++) {
if (dfn[i] == 0) {
dfs(i, -1);
}
}
}
vector<vector<int>> rebuild()
{
int cnt = ebcc.size();
vector<vector<int>>g(cnt);
for (int u = 1; u <= n; u++) {
for (auto [v, _] : adj[u]) {
if (bel[u] != bel[v]) {
g[bel[u]].push_back(bel[v]);
}
}
}
return g;
}
}; struct SCC {
// scc 数组逆序满足拓扑序
int n;
vector<vector<int>>& adj;
vector<vector<int>> scc;
vector<int> stk;
vector<int> dfn, low, bel;
int cur, cnt;
SCC(int n_, vector<vector<int>>& adj_) : adj(adj_), n(n_) { init(n); }
void init(int n)
{
this->n = n;
dfn.assign(n + 1, 0);
low.resize(n + 1);
bel.assign(n + 1, -1);
stk.clear();
cur = 0;
work();
}
void dfs(int x)
{
dfn[x] = low[x] = ++cur;
stk.push_back(x);
deb(stk);
for (auto y : adj[x]) {
deb(x, y);
if (dfn[y] == 0) {
dfs(y);
low[x] = min(low[x], low[y]);
}
else if (bel[y] == -1) {
low[x] = min(low[x], dfn[y]);
}
}
if (dfn[x] == low[x]) {
int cnt = scc.size();
scc.push_back({});
int y;
do {
y = stk.back();
bel[y] = cnt;
stk.pop_back();
scc.back().push_back(y);
} while (y != x);
}
}
void work()
{
for (int i = 1; i <= n; i++) {
if (dfn[i] == 0) {
dfs(i);
}
}
}
};
void solve()
{
int n, m;
cin >> n >> m;
vector<vector<int>>adj(n + 1);
for (int i = 1; i <= m; i++) {
int x, y;
cin >> x >> y;
x++, y++;
adj[x].push_back(y);
}
SCC Scc(n, adj);
auto& scc = Scc.scc;
cout << scc.size() << "\n";
for (auto p : scc) {
cout << p.size() << " ";
for (auto x : p) {
cout << x - 1 << " \n"[x == p.back()];
}
}
}
int main()
{
#ifdef LOCAL
#ifdef OPENSTACK
int size = 128 << 20; // 64MB
char* p = (char*) malloc(size) + size;
#if (defined _WIN64) or (defined __unix)
__asm__("movq %0, %%rsp\n" ::"r"(p));
#else
__asm__("movl %0, %%esp\n" ::"r"(p));
#endif
#endif
#endif
IOS;
int _ = 1;
while (_--) {
solve();
}
#ifdef LOCAL
#ifdef OPENSTACK
exit(0);
#else
return 0;
#endif
#endif
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Wrong Answer
time: 0ms
memory: 3616kb
input:
6 7 1 4 5 2 3 0 5 5 4 1 0 3 4 2
output:
4 2 3 0 1 2 2 4 1 1 5
result:
wrong answer 5 is later than 2, but there is an edge (5, 2)