Pagini recente » Cod sursa (job #3283293) | Cod sursa (job #1712164) | Cod sursa (job #2485290) | Cod sursa (job #269699) | Cod sursa (job #2787477)
#include <iostream>
#include <list>
#include <fstream>
#include <vector>
#include <stack>
// Link pt `GraphSolver`: https://github.com/Andrei0872/Algorithms/blob/master/GraphSolver/main.cpp
using namespace std;
list<int>* adjList;
stack<int> visitedNodes;
vector<vector<int>> SCCs;
bool* isInStack;
bool* visited;
int* ingressTimestamp;
int* lowestReachableLevel;
void extractSCCFromStack (int startNodeIdx) {
vector<int> SCC;
int stackNodeIdx;
do {
stackNodeIdx = visitedNodes.top();
visitedNodes.pop();
isInStack[stackNodeIdx] = false;
SCC.push_back(stackNodeIdx);
} while (stackNodeIdx != startNodeIdx);
SCCs.push_back(SCC);
}
void printSCCs () {
ofstream out("ctc.out");
out << SCCs.size() << '\n';
for (auto SCC : SCCs) {
for (auto v : SCC) {
out << v << ' ';
}
out << '\n';
}
out.close();
}
void DFSforSCC (int crtNodeIdx) {
static int ingressCount = 0;
visited[crtNodeIdx] = true;
// At the beggining, both are the same.
ingressTimestamp[crtNodeIdx] = lowestReachableLevel[crtNodeIdx] = ingressCount++;
// A node which is part of the stack can belong to a SCC.
visitedNodes.push(crtNodeIdx);
isInStack[crtNodeIdx] = true;
for (int childNodeIdx : adjList[crtNodeIdx]) {
// In a SCC, all its nodes must be able to reach each other.
// To that end, it is expected to encounter cycles and that's why we're traversing
// the children first. Considering that each node is given an `ingressTimestamp`,
// if a cycle is encountered, the already visited node will have a **smaller** `ingressTimestamp`.
// We will form a SCC by grouping having all its constituent the same `ingressTimestamp`.
if (!visited[childNodeIdx]) {
DFSforSCC(childNodeIdx);
}
// If the child is still in stack it means that it is not yet part
// of a different SCC.
if (isInStack[childNodeIdx]) {
lowestReachableLevel[crtNodeIdx] = min(lowestReachableLevel[crtNodeIdx], lowestReachableLevel[childNodeIdx]);
}
}
bool isStartOfSCC = lowestReachableLevel[crtNodeIdx] == ingressTimestamp[crtNodeIdx];
if (isStartOfSCC) {
extractSCCFromStack(crtNodeIdx);
}
}
void initializeStructures (int N) {
adjList = new list<int>[N + 1];
isInStack = new bool[N + 1];
visited = new bool[N + 1];
ingressTimestamp = new int[N + 1];
lowestReachableLevel = new int[N + 1];
for (int i = 1; i <= N; i++) {
visited[i] = isInStack[i] = false;
}
}
void teardown () {
delete[] adjList;
delete isInStack;
delete visited;
delete ingressTimestamp;
delete lowestReachableLevel;
}
int main () {
ifstream in("ctc.in");
int N, M;
in >> N >> M;
initializeStructures(N);
int x, y;
for (int i = 0; i < M; i++) {
in >> x >> y;
adjList[x].push_back(y);
}
in.close();
for (int i = 1; i <= N; i++) {
if (!visited[i]) {
DFSforSCC(i);
}
}
printSCCs();
teardown();
}