Pagini recente » Cod sursa (job #1624189) | Cod sursa (job #42979) | Cod sursa (job #1141490) | Cod sursa (job #165001) | Cod sursa (job #459618)
Cod sursa(job #459618)
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>
#include <fstream>
using namespace std;
typedef unsigned int uint;
/**
* A normal stack class that can check in constant time if a
* certain element is contained within the stack.
*/
class Stack
{
public:
Stack(uint maxSize)
{
stack.reserve(maxSize + 1);
isInStack.resize(maxSize + 1, false);
}
public:
void push(uint node)
{
stack.push_back(node);
isInStack[node] = true;
}
uint peek() const { return stack.back(); }
uint pop()
{
uint node = stack.back();
stack.pop_back();
isInStack[node] = false;
return node;
}
bool isEmpty() const { return stack.empty(); }
bool contains(uint node) { return isInStack[node]; }
private:
std::vector<bool> isInStack;
std::vector<uint> stack;
};
/**
* More like a "half" edge.
*/
class Edge
{
public:
Edge(uint destNode)
: dest(destNode), next(0)
{}
public:
uint dest;
Edge * next;
};
/**
* Class used to represent/store a directed graph using an
* adjacency list.
*/
class AdjacencyList
{
public:
AdjacencyList(uint nodes)
: numNodes(nodes)
{
list.resize(nodes + 1, NULL);
}
~AdjacencyList()
{
for(uint i = 0; i < list.size(); i++)
{
if(list[i])
{
Edge * current = list[i];
while(current)
{
Edge * deleted = current;
current = current->next;
delete deleted;
}
}
}
}
public:
void insertEdge(uint src, uint dest)
{
if(!list[src])
{
list[src] = new Edge(dest);
}
else
{
Edge * e = new Edge(dest);
e->next = list[src];
list[src] = e;
}
}
Edge * getEdges(uint node) { return list[node]; }
void print()
{
for(uint i = 0; i < list.size(); i++)
{
if(list[i])
{
Edge * e = list[i];
while(e)
{
cout << "(" << i << ", " << e->dest << ")" << endl;
e = e->next;
}
}
}
}
private:
std::vector<Edge *> list;
uint numNodes;
};
struct Component
{
Component() : next(0) {}
std::vector<uint> nodes;
Component * next;
};
/**
* A class used to determine the strongly connected components of a directed
* graph.
*/
class StronglyConnectedComponents
{
public:
StronglyConnectedComponents(
AdjacencyList& initGraph,
AdjacencyList& transGraph,
Stack& stack,
uint nodes
)
: graph(initGraph), transposeGraph(transGraph),
nodeStack(stack), numNodes(nodes), numComponents(0)
{
visited.resize(nodes + 1, false);
whichComp.resize(nodes + 1, 0);
}
public:
void execute()
{
firstDfs();
secondDfs();
}
std::vector<uint> * getComponents() { return components; }
uint getNumComponents() { return numComponents; }
private:
/**
* The first depth first search just goes through the graph
* and creates a stack of all the nodes, such that the node
* at the top of the stack is the node with the maximum finishing
* time.
*/
void firstDfs()
{
for(uint node = 1; node <= numNodes; node++)
{
if(!visited[node])
firstDfsRecursive(node);
}
}
void firstDfsRecursive(uint node = 1)
{
visited[node] = true;
for(Edge * edge = graph.getEdges(node);
edge != 0;
edge = edge->next)
{
if(!visited[edge->dest])
firstDfsRecursive(edge->dest);
}
nodeStack.push(node);
}
void secondDfs()
{
while(!nodeStack.isEmpty())
{
numComponents++;
secondDfsRecursive(nodeStack.peek());
while(!nodeStack.isEmpty() && whichComp[nodeStack.peek()] != 0)
nodeStack.pop();
}
components = new std::vector<uint>[numComponents];
for(uint i = 1; i <= numNodes; i++)
{
components[whichComp[i] - 1].push_back(i);
}
}
void secondDfsRecursive(uint node)
{
/**
* In this case we think of the visited vector as representing
* a "not-visited" vector. This way we save the space and hassle
* of creating another visited vector for the second search.
*/
visited[node] = false;
whichComp[node] = numComponents;
for(Edge * edge = transposeGraph.getEdges(node);
edge != 0;
edge = edge->next)
{
if(visited[edge->dest])
secondDfsRecursive(edge->dest);
}
}
private:
AdjacencyList& graph;
AdjacencyList& transposeGraph;
Stack& nodeStack;
uint numNodes;
uint numComponents;
std::vector<bool> visited;
std::vector<uint> whichComp;
std::vector<uint> * components;
};
int main()
{
const char * inFile = "ctc.in";
const char * outFile = "ctc.out";
ifstream fin(inFile);
uint numNodes, numEdges;
fin >> numNodes >> numEdges;
AdjacencyList graph(numNodes);
AdjacencyList transposeGraph(numNodes);
Stack nodeStack(numNodes);
for(uint i = 0; i < numEdges; i++)
{
uint x, y;
fin >> x >> y;
graph.insertEdge(x, y);
transposeGraph.insertEdge(y, x);
}
fin.close();
StronglyConnectedComponents scc(graph, transposeGraph, nodeStack, numNodes);
scc.execute();
ofstream fout(outFile);
uint numComponents = scc.getNumComponents();
fout << numComponents << "\n";
std::vector<uint> * component = scc.getComponents();
for(uint i = 0; i < numComponents; i++)
{
for(uint j = 0; j < component[i].size(); j++)
{
fout << component[i][j] << " ";
}
fout << "\n";
}
fout.close();
return 0;
}