Pagini recente » Cod sursa (job #1667152) | Cod sursa (job #2678899) | Cod sursa (job #2136580) | Cod sursa (job #2563077) | Cod sursa (job #2866228)
#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <forward_list>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
/* Defines */
using i32 = int32_t;
using u32 = uint32_t;
using Edges = std::vector<std::vector<std::pair<size_t, u32>>>; // [node] -> [toNode, edgeIndex];
constexpr const char *inputFilename = "ciclueuler.in";
constexpr const char *outputFilename = "ciclueuler.out";
constexpr u32 MAX_EDGES = 500000;
/* Function definitions */
Edges readInput();
bool allNodesHaveEvenDegree(const Edges &graph);
std::forward_list<size_t> findEulerianCycle(const Edges &edges);
void consumeCycle(const size_t start, Edges &edges, std::array<bool, MAX_EDGES>& usedEdge,
std::forward_list<size_t> &result, std::forward_list<size_t>::iterator journal);
void dropBackUsedEdges(Edges::value_type &toEdges, const std::array<bool, MAX_EDGES>& usedEdge);
void writeNoAnswer();
void writeResult(const std::forward_list<size_t> &result);
/* Global variables */
/* Function declarations */
Edges readInput () {
std::ifstream file(inputFilename);
file.exceptions(file.badbit | file.eofbit | file.failbit);
size_t nodesCount;
u32 edgeCount;
file >> nodesCount >> edgeCount;
Edges edges(nodesCount);
for (u32 edge = 0; edge != edgeCount; ++ edge) {
size_t from, to;
file >> from >> to;
-- from, -- to;
edges[from].emplace_back(to, edge);
edges[to].emplace_back(from, edge);
}
return edges;
}
bool allNodesHaveEvenDegree (const Edges &graph) {
std::vector<bool> parityOfDegree(graph.size());
for (size_t i = 0; i != graph.size(); ++ i)
for (auto [j, _]: graph[i]) {
if (i <= j) {
parityOfDegree[i] = !parityOfDegree[i];
parityOfDegree[j] = !parityOfDegree[j];
}
}
return std::all_of(parityOfDegree.begin(), parityOfDegree.end(), [](auto x){ return x == false; });
}
std::forward_list<size_t> findEulerianCycle (const Edges &ogEdges) {
std::forward_list<size_t> result({0});
Edges edges = ogEdges;
std::array<bool, MAX_EDGES> usedEdge({});
for (auto it = result.begin(); it != result.end();) {
dropBackUsedEdges(edges[*it], usedEdge);
if (edges[*it].empty()) {
++ it;
continue;
}
consumeCycle(*it, edges, usedEdge, result, it);
}
return result;
}
void consumeCycle(const size_t start, Edges &edges, std::array<bool, MAX_EDGES>& usedEdge,
std::forward_list<size_t> &result, std::forward_list<size_t>::iterator journal) {
size_t node = start;
do {
dropBackUsedEdges(edges[node], usedEdge);
auto [toNode, edgeIndex] = edges[node].back();
edges[node].pop_back();
usedEdge[edgeIndex] = true;
node = toNode;
journal = result.emplace_after(journal, node);
} while (node != start);
}
void dropBackUsedEdges (Edges::value_type &toEdges, const std::array<bool, MAX_EDGES>& usedEdge) {
while (!toEdges.empty() && usedEdge[toEdges.back().second])
toEdges.pop_back();
}
void writeNoAnswer () {
std::ofstream output(outputFilename);
output.exceptions(output.badbit | output.eofbit | output.failbit);
output << "-1\n";
}
void writeResult (const std::forward_list<size_t> &result) {
std::ofstream output(outputFilename);
output.exceptions(output.badbit | output.eofbit | output.failbit);
for (auto it = std::next(result.begin()); it != result.end(); ++ it)
output << *it + 1 << ' ';
output.put('\n');
}
int main () {
const Edges edges(readInput());
if (!allNodesHaveEvenDegree(edges))
writeNoAnswer();
else
writeResult(findEulerianCycle(edges));
}