cp-library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub Oxojo/cp-library

:heavy_check_mark: verify/yosupo/scc.test.cpp

Depends on

Code

// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/scc

#include "../../library/template/template.hpp"
#include "../../library/graph/graph.hpp"
#include "../../library/graph/scc.hpp"
void solve() {
	ll n, m; in(n, m);
	scc<ll> g(n);
	g.read(m, 0, 0, 1);
	g.build();
	cout << sz(g.group) << endl;
	fore(p, g.group) {
		cout << sz(p) << ' ' << p;
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(12);
	ll T = 1;
	// cin >> T;
	while (T--) solve();
}
#line 1 "verify/yosupo/scc.test.cpp"
// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/scc

#line 2 "library/template/template.hpp"

#include <bits/stdc++.h>
using namespace std;

// def for types
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
using pll = pair<ll, ll>;
template <class T> using vec = vector<T>;
template <class T> using vv = vec<vec<T>>;
template <class T> using vvv = vv<vec<T>>;
using vl = vec<ll>;
using vd = vec<ld>;
using vs = vec<string>;
using vvl = vv<ll>;
template <class T> using minpq = priority_queue<T, vector<T>, greater<T>>;
using vp = vec<pll>;

// const
const ll INF = numeric_limits<ll>::max() / 4;
const ld inf = numeric_limits<ld>::max() / 2;
const ll mod1 = 1000000007;
const ll mod2 = 998244353;
const ld pi = 3.141592653589793238;

// macro
#define rep(i, r) for (ll i = 0; i < (r); i++)
#define reps(i, l, r) for (ll i = (l); i < (r); i++)
#define rrep(i, l, r) for (ll i = (r) - 1; i >= l; i--)
#define fore(e, v) for (auto &&e : v)
#define eb emplace_back
#define pb push_back
#define fi first
#define se second
#define all(a) begin(a),end(a)
#define emp(a) a.empty()
	
// func for vector
template <class T> 
ll sz(const T &t) { return (ll)t.size(); }
template <class T>
inline T vmax(const vec<T> &v) { return *max_element(all(v)); }
template <class T>
inline T vmin(const vec<T> &v) { return *min_element(all(v)); }
template <class T>
inline T Sum(const vec<T> &v) {
	return accumulate(all(v), T(0));
}
template <class T>
ll lb(const vec<T> &v, const T &a) { return lower_bound(all(v), a) - begin(v); }
template <class T>
ll ub(const vec<T> &v, const T &a) { return upper_bound(all(v), a) - begin(v); }
template <class T>
void mkuniq(T &a) { sort(all(a));	a.erase(unique(all(a)), a.end()); }
template <class T>
void mkrev(T &a) { reverse(all(a)); }
vl mkiota(ll n) { vl ret(n); iota(all(ret), 0ll); return ret; }
template <class T>
vl mkinv(vec<T> &v) {
	vl inv(vmax(v), -1);
	rep(i, sz(v)) inv[v[i]] = i;
	return inv;
}
template <class F>
vl mkorf(ll n, F f) {
	vl ord(n);
	iota(all(ord), 0ll);
	sort(all(ord), f);
	return ord;
}
template <class T>
vl mkcum(const vec<T> &v, bool rev = false) {
	vec<T> ret(sz(v) + 1);
	if (rev) {
		rrep(i, 0, sz(v)) ret[i] = v[i] + ret[i + 1];
	} else {
		rep(i, sz(v)) ret[i + 1] = ret[i] + v[i];
	}
	return ret;
}
template <class T>
bool nxp(T &v) { return next_permiutation(all(v)); }

//in-out
template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T1, class T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
ostream &operator<<(ostream &os, const vec<T> &v) {
	rep(i, sz(v)) os << v[i] << " \n"[i + 1 == sz(v)];
	return os;
}
template <class T>
istream &operator>>(istream &is, vec<T> &v) {
	for (T &in : v) is >> in;
	return is;
}
istream &operator>>(istream &is, i128 &x) {
	string s; is >> s;
	x = 0;
	bool flag = 0;
	fore(c, s) {
		if (c == '-') {
			flag = true; continue;
		}
		x *= 10; x += c - '0';
	}
	if (flag) x = -x;
	return is;
}
istream &operator>>(istream &is, u128 &x) {
	string s; is >> s;
	x = 0;
	fore(c, s) {
		x *= 10; x += c - '0';
	}
	return is;
}
ostream &operator<<(ostream &os, i128 x) {
	if (x == 0) return os << 0;
	if (x < 0) os << '-', x = -x;
	string s;
	while (x) s.pb('0' + x % 10), x /= 10;
	mkrev(s);
	return os << s;
}
ostream &operator<<(ostream &os, u128 x) {
	if (x == 0) return os << 0;
	string s;
	while (x) s.pb('0' + x % 10), x /= 10;
	mkrev(s);
	return os << s;
}
void in(){}
template <class T, class... U>
void in(T &t, U &...u) {
	cin >> t;
	in(u...);
}
void out(){}
template <class T, class...U, char sep = ' '>
void out(const T &t, const U &...u) {
	cout << t;
	if (sizeof...(u)) cout << sep;
	out(u...);
}

// func for bit
ll popcnt(ll &a) { return __builtin_popcountll(a); }
inline int lsb(const ull &a) { return a ? __builtin_ctzll(a) : 64; }
inline int msb(const ull &a) { return a ? 63 - __builtin_ctzll(a) : -1; }
inline ll getbit(const ll &a, ll i) { return (a >> i) & 1; }
inline void setbit(ll &a, ll i) { a |= (1ll << i); }
inline void delbit(ll &a, ll i) { a &= ~(1ll << i); }
constexpr ll pw(ll n) { return 1ll << n; }
constexpr ll msk(ll n) { return (1ll << n) - 1; }

// func for math
template <class T>
bool btw(T a, T x, T b, bool left, bool right) {
	bool l, r;
	if (left) l = (a <= x);
	else l = (a < x);
	if (right) r = (x <= r);
	else r = (x < r);
	return l && r;
}
template <class T, class U>
T ceil(T a, U b) { return (a + b - 1) / b; }

// uncategorized
template <class T>
inline bool chmax(T &a, const T &b) { return a < b ? a = b, true : false; }
template <class T>
inline bool chmin(T &a, const T &b) { return a > b ? a = b, true : false; }
constexpr ll ten(ll n) {
	ll ret = 1, x = 10;
	for(; n; x *= x, n >>= 1) ret *= (n & 1 ? x : 1);
	return ret;
}
bool yesno(bool t) {
	cout << (t ? "Yes" : "No") << endl;
	return t;
}
template <class T>
vv<T> tramspose(const vec<T> &v) {
	if (emp(v)) return {};
	ll h = sz(v), w = sz(v[0]);
	vv<T> res(w, vec<T>(h, T()));
	rep(i, h) rep(j, w) {
		res[j][i] = v[i][j];
	}
	return res;
}
template <class T>
vv<T> rotate(const vec<T> &v, bool cw = true) {
	ll h = sz(v), w = sz(v[0]);
	vv<T> res(w, vec<T>(h, T()));
	rep(i, h) rep(j, w) {
		if (cw) res[w - 1 - j][i] = v[i][j];
		else res[j][h - 1 - i] = v[i][j];
	}
	return res;
}
template <class T>
bool sfind(set<T>&s, T key) {
	return s.find(key) != s.end();
}
#line 2 "library/graph/graph.hpp"

#line 4 "library/graph/graph.hpp"

template <typename T = ll>
struct Edge {
    ll from, to;
    T cost;
    
    Edge() = default;

    Edge(ll from, ll to, T cost = T(1)) : from(from), to(to), cost(cost) {}

	operator ll() const { return to; }
};

template <typename T = ll>
struct Graph {
    vv<Edge<T>> g;
    
    Graph() = default;

    explicit Graph(ll n) : g(n) {}

    size_t size() const { return g.size(); }

    void add(ll from, ll to, T cost = 1, bool direct = false) {
        g[from].eb(from, to, cost);
        if (!direct) g[to].eb(to, from, cost);
    }

    void read(ll m, ll padding = -1, bool weight = false, bool direct = false) {
        rep(i, m) {
            ll a, b; in(a, b);
            a += padding, b += padding;
            T c = T(1);
            if (weight) in(c);
            add(a, b, c, direct);
        }
    }

    inline vec<Edge<T>>& operator[](const ll& k) { return g[k]; }

    inline const vec<Edge<T>>& operator[](const ll& k) const { return g[k]; }
};

template <typename T = ll> using Edges = vec<Edge<T>>;
#line 2 "library/graph/scc.hpp"

#line 5 "library/graph/scc.hpp"

template <typename T = ll>
struct scc : Graph<T> {
public:
    using Graph<T>::Graph;
    using Graph<T>::g;
    vl cmp;
    Graph<T> dag;
    vv<ll> group;

    void build() {
        rg = Graph<T>(sz(g));
        rep(i, sz(g)) fore(e, g[i]) {
            rg.add(e.to, e.from, e.cost, 1);
        }
        cmp.assign(sz(g), -1);
        use.assign(sz(g), 0);
        rep(i,sz(g)) dfs(i);
        mkrev(ord);
        ll ptr = 0;
        for (ll i : ord) {
            if (cmp[i] == -1) rdfs(i, ptr), ptr++;
        }
        dag = Graph<T>(ptr);
        rep(i, sz(g)) {
            fore(e, g[i]) {
                ll x = cmp[e.from], y = cmp[e.to];
                if (x == y) continue;
                dag.add(x, y, e.cost, 1);
            }
        }
        group.resize(ptr);
        rep(i, sz(g)) group[cmp[i]].eb(i);
    }

    ll operator[](ll k) const { return cmp[k]; }

private:
    vl ord, use;
    Graph<T> rg;

    void dfs(ll idx) {
        if (exchange(use[idx], true)) return;
        fore(to, g[idx]) dfs(to);
        ord.pb(idx);
    }

    void rdfs(ll idx, ll cnt) {
        if (cmp[idx] != -1) return;
        cmp[idx] = cnt;
        fore(to, rg.g[idx]) rdfs(to, cnt);
    }
};
#line 6 "verify/yosupo/scc.test.cpp"
void solve() {
	ll n, m; in(n, m);
	scc<ll> g(n);
	g.read(m, 0, 0, 1);
	g.build();
	cout << sz(g.group) << endl;
	fore(p, g.group) {
		cout << sz(p) << ' ' << p;
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(12);
	ll T = 1;
	// cin >> T;
	while (T--) solve();
}

Test cases

Env Name Status Elapsed Memory
g++ example_00 :heavy_check_mark: AC 5 ms 4 MB
g++ large_cycle_00 :heavy_check_mark: AC 232 ms 75 MB
g++ max_random_00 :heavy_check_mark: AC 420 ms 126 MB
g++ max_random_01 :heavy_check_mark: AC 408 ms 126 MB
g++ max_random_02 :heavy_check_mark: AC 433 ms 126 MB
g++ max_random_03 :heavy_check_mark: AC 387 ms 126 MB
g++ max_random_04 :heavy_check_mark: AC 394 ms 126 MB
g++ random_00 :heavy_check_mark: AC 394 ms 101 MB
g++ random_01 :heavy_check_mark: AC 324 ms 112 MB
g++ random_02 :heavy_check_mark: AC 120 ms 37 MB
g++ random_03 :heavy_check_mark: AC 92 ms 70 MB
g++ random_04 :heavy_check_mark: AC 99 ms 56 MB
clang++ example_00 :heavy_check_mark: AC 5 ms 4 MB
clang++ large_cycle_00 :heavy_check_mark: AC 257 ms 83 MB
clang++ max_random_00 :heavy_check_mark: AC 414 ms 126 MB
clang++ max_random_01 :heavy_check_mark: AC 402 ms 126 MB
clang++ max_random_02 :heavy_check_mark: AC 418 ms 126 MB
clang++ max_random_03 :heavy_check_mark: AC 422 ms 126 MB
clang++ max_random_04 :heavy_check_mark: AC 428 ms 126 MB
clang++ random_00 :heavy_check_mark: AC 367 ms 102 MB
clang++ random_01 :heavy_check_mark: AC 341 ms 112 MB
clang++ random_02 :heavy_check_mark: AC 122 ms 38 MB
clang++ random_03 :heavy_check_mark: AC 85 ms 69 MB
clang++ random_04 :heavy_check_mark: AC 102 ms 55 MB
Back to top page