Pagini recente » Cod sursa (job #517154) | Cod sursa (job #412602) | Cod sursa (job #2463266) | Cod sursa (job #507493) | Cod sursa (job #2925578)
#include <bits/stdc++.h>
using namespace std;
vector<int> finishingTime;
bool defaultComparator(int a, int b) {
return finishingTime[a] > finishingTime[b];
}
ifstream fin("ctc.in");
ofstream fout("ctc.out");
std::stringstream ssResult;
class Graph {
private:
vector<vector<int>> adjList;
int N;
int M;
Graph* transposed = nullptr;
bool modifiedSinceLastTransposal;
int numberOfVisitedNodes;
void _DFS(int currentNode, bool printOutput = false) {
if(printOutput) {
ssResult << currentNode << " ";
}
visited[currentNode] = true;
for(int j = 0; j < adjList[currentNode].size();j++) {
if(!visited[adjList[currentNode][j]]) {
_DFS(adjList[currentNode][j], printOutput);
}
}
finishingTime[currentNode] = ++numberOfVisitedNodes;
}
public:
vector<bool> visited;
Graph(int N, int M) {
this->N = N;
this->M = M;
this->adjList = vector<vector<int>>(N+1);
this->modifiedSinceLastTransposal = true;
this->numberOfVisitedNodes = 0;
this->visited = vector<bool>(N+1);
}
void addEdge(int x, int y) {
if(std::find(adjList[x].begin(), adjList[x].end(), y) == adjList[x].end()) {
this->adjList[x].push_back(y);
}
this->modifiedSinceLastTransposal = true;
}
void printAdjList() {
for(int i = 1; i <= N; i++) {
for(int j = 0; j < adjList[i].size(); j++) {
cout << adjList[i][j] << " ";
}
cout << "\n";
}
}
Graph& getTransposed() {
if(transposed == nullptr || modifiedSinceLastTransposal) {
if(transposed != nullptr) {
delete transposed;
}
transposed = new Graph(N, M);
for(int i = 1; i <= N; i++) {
for(int j = 0; j < adjList[i].size(); j++) {
transposed->addEdge(adjList[i][j], i);
}
}
modifiedSinceLastTransposal = false;
}
return *transposed;
}
void DFS(int currentNode, bool reinitializeInternalVars = true, bool(*comparator) (int, int) = defaultComparator, bool printOutput=false) {
// This is a wrapper method over the actual DFS implementation in order to remove the necessity of re-initializing this by the function caller
// every time a DFS is made
// Re-initialize the visited array and the number of visited nodes
if(reinitializeInternalVars) {
numberOfVisitedNodes = 0;
std::fill(visited.begin(), visited.end(), 0);
}
// Sort the adjacency lists of every node with respect to the provided comparator
for(int i = 1; i <= N; i++) {
sort(adjList[i].begin(), adjList[i].end(), comparator);
}
_DFS(currentNode, printOutput);
}
void computeDFSFinishingTimes() {
numberOfVisitedNodes = 0;
std::fill(visited.begin(), visited.end(), 0);
for(int i = 1; i <= N;i++) {
if(!visited[i]) {
DFS(i, false, defaultComparator, false);
}
}
// cout << "\nFinishing times are the following: ";
// for(int i = 1; i <= N;i++) {
// cout << finishingTime[i] << " ";
// }
// cout << "\n";
}
};
int main() {
int N, M;
int x, y;
fin >> N >> M;
finishingTime = vector<int> (N+1);
Graph G {N, M};
for(int i = 0; i<M;i++) {
fin >> x >> y;
G.addEdge(x, y);
}
Graph GT = G.getTransposed();
// cout << "DFS for graph G:\n";
G.computeDFSFinishingTimes();
// cout << "\n";
//cout << "DFS finishing times for graph G are: ";
// for(int i = 1; i<=N; i++) {
// cout << finishingTime[i] << " ";
// }
// cout << "\n";
// // DFS for transposed graph
// cout << "DFS for transposed graph:\n";
int nrComp = 0;
vector<int> listOfNodes = vector<int>(N+1);
for(int i = 1; i<=N;i++) {
listOfNodes[N - finishingTime[i] + 1] = i;
}
for(int i = 1; i<=N; i++) {
if(!GT.visited[listOfNodes[i]]) {
nrComp++;
GT.DFS(listOfNodes[i], false, defaultComparator, true);
ssResult << "\n";
}
}
fout << nrComp << "\n";
fout << ssResult.rdbuf();
return 0;
}