#include #include #include #include #include #pragma region Region_1 #define per(name, beg, en) for (int name = beg; name <= en; ++name) #define rep(name, beg, en) for (int name = beg; name >= en; --name) #define pb push_back #define mp make_pair #define sz(x) (int)(x).size() #define F first #define S second #define FF first.first #define FS first.second #define SF second.first #define SS second.second #pragma endregion using namespace std; class Timer { private: // Псевдонимы типов используются для удобного доступа к вложенным типам using clock_t = std::chrono::high_resolution_clock; using second_t = std::chrono::duration >; std::chrono::time_point m_beg; double last_elapsed; public: Timer() : m_beg(clock_t::now()), last_elapsed(0) { } void reset() { m_beg = clock_t::now(); last_elapsed = 0.0; } double elapsed() { last_elapsed = std::chrono::duration_cast(clock_t::now() - m_beg).count(); return last_elapsed; } inline double getLastElapsed() { return last_elapsed; } }; using pii = pair; using GraphList = vector>; // Граф списком смежности using GraphMatrix = vector>; // Граф матрицей смежности const int inf = INT_MAX; const pii pinf = mp(inf, inf); /// /// Находит ребро с конечной вершиной [v] в списке смежности [vec] от начальной вершины /// /// - список смежности для начальной вершины /// - конечная вершина /// inline pii finder(const vector < pii >& vec, int v) { pii ans = pinf; ans.F = v; for (const auto& x : vec) if (x.F == v && x.S < ans.S) { ans = x; } return ans; } inline void matrixPrinter(const GraphMatrix& graph, ostream& out) { size_t size = graph.size(); per(u, 1, size - 1) { per(v, 1, size - 1) out << ((graph[u][v] == inf) ? 0 : graph[u][v]) << " \t"; out << endl; } } inline void listPrinter(const GraphMatrix& graph, ostream& out) { size_t size = graph.size(); per(u, 1, size - 1) { per(v, 1, size - 1) { if (u != v && graph[u][v] != inf) { out << u << " \t" << v << " \t" << graph[u][v] << endl; } } } } /// /// Алгоритм Флойда от матрицы смежности /// /// Начальная матрица смежности, она же результат работы inline void _floyd(GraphMatrix& sD, int numThreads = omp_get_max_threads()) { size_t size = sD.size(); for (int i = 1; i < size; i++) { #pragma omp parallel for num_threads(numThreads) schedule(dynamic, 200) for (int u = 1; u < size; u++) { for (int v = 1; v < size; v++) { if (sD[u][i] < inf && sD[i][v] < inf) sD[u][v] = min(sD[u][v], sD[u][i] + sD[i][v]); } } } } void floydAlgMatrix(const GraphMatrix& graph, ostream& out, int numThreads = omp_get_max_threads()) { //GraphMatrix sD = graph; GraphMatrix sD; int size = static_cast(sz(graph)); sD.resize(size); #pragma omp parallel for num_threads(numThreads) per(u, 1, size - 1) { sD[u].resize(size); per(v, 1, size - 1) if (graph[u][v] != 0) sD[u][v] = graph[u][v]; else sD[u][v] = inf; } _floyd(sD, numThreads); listPrinter(sD, out); } void floydAlgList(const GraphList& graph, ostream& out, int numThreads = omp_get_max_threads()) { GraphMatrix sD; int size = static_cast(sz(graph)); sD.resize(size); #pragma omp parallel for num_threads(numThreads) per(i, 1, size - 1) { sD[i].pb(0); // Заполняем нулевые элементы каждого ряда per(j, 1, size - 1) { sD[i].pb(finder(graph[i], j).S); } } _floyd(sD, numThreads); listPrinter(sD, out); } // Ввод данных и вызов методов void solve(int num_threads) { ifstream in("input.txt"); if (!in.is_open()) throw exception("File input.txt wasn't open!"); int n, m; in >> n >> m; GraphMatrix matrixGraph; // граф матрицей смежности GraphList listGraph; // граф списком смежности listGraph.resize(n + 1); matrixGraph.resize(n + 1); per(i, 1, n) matrixGraph[i].resize(n + 1, 0); per(i, 1, m) { int u, v, w; in >> u >> v >> w; matrixGraph[u][v] = matrixGraph[v][u] = (matrixGraph[u][v] == 0 ? w : min(w, matrixGraph[u][v])); listGraph[u].pb(mp(v, w)); listGraph[v].pb(mp(u, w)); } in.close(); ofstream outMatrix("output.txt"); Timer timer; floydAlgMatrix(matrixGraph, outMatrix, num_threads); timer.elapsed(); cout << "Алгоритм по матрице завершил работу за " << timer.getLastElapsed() << " секунд" << endl; outMatrix.close(); ofstream outList("output.txt"); timer.reset(); floydAlgList(listGraph, outList, num_threads); timer.elapsed(); cout << "Алгоритм по листу завершил работу за " << timer.getLastElapsed() << " секунд" << endl; outList.close(); } int main() { setlocale(LC_ALL, "ru"); vector numThreadsList = { 1 }; for (int i = 2; i <= omp_get_max_threads(); i += 2) numThreadsList.push_back(i); for (auto& numThreads : numThreadsList) { cout << "************************************" << endl; cout << "Работа алгоритмов для [" << numThreads << "] потоков: " << endl << endl; solve(numThreads); cout << "************************************" << endl << endl; } }