QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#586811#906. 强连通分量xorzjWA 0ms3616kbC++174.7kb2024-09-24 15:43:192024-09-24 15:43:20

Judging History

你现在查看的是最新测评结果

  • [2024-09-24 15:43:20]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:3616kb
  • [2024-09-24 15:43:19]
  • 提交

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)