Cod sursa(job #2662029)

Utilizator retrogradLucian Bicsi retrograd Data 23 octombrie 2020 12:08:44
Problema Componente tare conexe Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.5 kb
#include <bits/stdc++.h>

using namespace std;
using ull = unsigned long long;

class InParser {
private:
  FILE *fin;
  char *buff;
  int sp;
 
  char read_ch() {
    ++sp;
    if (sp == 4096) {
      sp = 0;
      fread(buff, 1, 4096, fin);
    }
    return buff[sp];
  }
 
public:
  InParser(const char* nume) {
    fin = fopen(nume, "r");
    buff = new char[4096]();
    sp = 4095;
  }
  
  InParser& operator >> (int &n) {
    char c;
    while (!isdigit(c = read_ch()) && c != '-');
    int sgn = 1;
    if (c == '-') {
      n = 0;
      sgn = -1;
    } else {
      n = c - '0';
    }
    while (isdigit(c = read_ch())) {
      n = 10 * n + c - '0';
    }
    n *= sgn;
    return *this;
  }
  
  InParser& operator >> (long long &n) {
    char c;
    n = 0;
    while (!isdigit(c = read_ch()) && c != '-');
    long long sgn = 1;
    if (c == '-') {
      n = 0;
      sgn = -1;
    } else {
      n = c - '0';
    }
    while (isdigit(c = read_ch())) {
      n = 10 * n + c - '0';
    }
    n *= sgn;
    return *this;
  }
};

vector<vector<ull>> adj, jda;
vector<ull> vis;
vector<int> stk, comp;

void AddEdge(int a, int b) {
  adj[a][b / 64] |= (1ULL << (b % 64));
  jda[b][a / 64] |= (1ULL << (a % 64));
}

int Pop(vector<ull>& a, vector<ull>& b) {
  for (int i = 0; i < (int)a.size(); ++i) {
    ull msk = (a[i] & (~b[i]));
    if (msk) 
      return __builtin_ctzll(msk) + i * 64;
  }
  return -1;
}

template<int Phase>
void DFS(int node) {
  vis[node / 64] |= (1LL << (node % 64));
  while (true) {
    int vec = Pop((Phase == 0 ? adj : jda)[node], vis);
    if (vec == -1) break;
    DFS<Phase>(vec);
  }
  (Phase == 0 ? stk : comp).push_back(node);
}

void Solve(ostream& cout) {
  int n = adj.size();
  
  vis.assign(n / 64 + 1, 0);
  for (int node = 0; node < n; ++node) {
    if (!(vis[node / 64] & (1ULL << (node % 64))))
      DFS<0>(node);
  }
  
  fill(vis.begin(), vis.end(), 0); 
  vector<int> ccs_end;
  for (int i = n - 1; i >= 0; --i) {
    int node = stk[i];
    if (!(vis[node / 64] & (1ULL << (node % 64)))) {
      DFS<1>(node);
      ccs_end.push_back(comp.size());
    }
  }

  cout << ccs_end.size() << '\n';
  int b = 0;
  for (auto e : ccs_end) {
    for (int i = b; i < e; ++i)
      cout << comp[i] + 1 << " ";
    cout << '\n';
    b = e;
  }
}

int main() {
  InParser cin("ctc.in");
  ofstream cout("ctc.out");
  int n, m; cin >> n >> m;
  adj.assign(n, vector<ull>(n / 64 + 1, 0));
  jda = adj;
  for (int i = 0; i < m; ++i) {
    int a, b; cin >> a >> b; --a; --b;
    AddEdge(a, b);
  }
  Solve(cout);
  return 0;
}