Pagini recente » Cod sursa (job #2016358) | Cod sursa (job #458032) | Cod sursa (job #434414) | Monitorul de evaluare | Cod sursa (job #1769749)
#include <fstream>
#include <vector>
#include <algorithm>
#include <utility>
#include <memory>
#include <iterator>
#include <stack>
namespace cpp14
{
template <class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) {return std::unique_ptr<T>(new T(std::forward<Args>(args)...));}
};
struct file_manip {
std::ifstream fin;
std::ofstream fout;
file_manip(const char* filename) {
std::string infilename = std::string(filename) + ".in";
std::string outfilename = std::string(filename) + ".out";
fin.open(infilename.c_str());
fout.open(outfilename.c_str());
}
template <class T>
file_manip& operator << (const T& rhs) {
fout << rhs;
return *this;
}
template <class T>
file_manip& operator >> (T& rhs) {
fin >> rhs;
return *this;
}
template <class T>
std::ostream_iterator<T> GetOstreamIterator() {
return std::ostream_iterator<T>(fout);
}
template <class T>
std::istream_iterator<T> GetIstreamIterator() {
return std::istream_iterator<T>(fin);
}
template <class T>
std::vector<T> ReadVector(int size)
{
std::vector<int> v;
v.reserve(size);
std::copy_n(GetIstreamIterator<int>(), size, std::back_inserter(v));
return v;
}
};
struct Graph
{
struct Vertex
{
static const auto UndefinedIndex = -1;
int index = UndefinedIndex, low_link = UndefinedIndex;
bool on_stack = false;
std::vector<int> neighbors;
int val;
Vertex(int val) : val(val) { }
void AddNeighbor(int x) { neighbors.push_back(x); }
};
std::vector<Vertex> vertices;
int N;
int index;
std::stack<int> S;
std::vector<int> solution;
void Init();
void Tarjan(file_manip& fm);
void StrongConnect(Vertex& v);
};
template <>
file_manip& file_manip::operator >> (Graph& rhs) {
fin >> rhs.N;
rhs.Init();
int M;
fin >> M;
while (M--)
{
int A, B;
fin >> A >> B;
rhs.vertices[A - 1].AddNeighbor(B - 1);
}
return *this;
}
void Graph::Init()
{
vertices.reserve(N);
for (int i = 0; i < N; ++i)
{
vertices.emplace_back(i);
}
solution.reserve(2 * N + 1);
solution.push_back(0);
}
void Graph::Tarjan(file_manip& fm)
{
index = 0;
for (auto& v : vertices)
{
if (v.index == Vertex::UndefinedIndex)
{
StrongConnect(v);
}
}
fm << solution[0] << "\n";
for (auto i = 1; i < solution.size(); ++i)
{
if (solution[i] == -1)
fm << "\n";
else
fm << solution[i] + 1 << " ";
}
solution.clear();
}
void Graph::StrongConnect(Vertex& v)
{
v.index = index;
v.low_link = index;
++index;
S.push(v.val);
v.on_stack = true;
for (const auto& w : v.neighbors)
{
if (vertices[w].index == Vertex::UndefinedIndex)
{
StrongConnect(vertices[w]);
v.low_link = std::min(v.low_link, vertices[w].low_link);
}
else if (vertices[w].on_stack)
{
v.low_link = std::min(v.low_link, vertices[w].index);
}
}
if (v.low_link == v.index)
{
++solution[0];
while (S.top() != v.val)
{
solution.push_back(S.top());
vertices[S.top()].on_stack = false;
S.pop();
}
solution.push_back(S.top());
vertices[S.top()].on_stack = false;
S.pop();
solution.push_back(-1);
}
}
int main()
{
file_manip fm("ctc");
Graph G;
fm >> G;
G.Tarjan(fm);
return 0;
}