По некоторым причинам в статье рассматриваются две близкие задачи. Приведенный программный код содержит все необходимые функции, для решения обеих. Вставляя или убирая комментарии в строках 129, 130 можно выбрать, какую из задач будет решать программа.
Полный ориентированный взвешенный граф задан матрицей смежности. Постройте матрицу кратчайших путей между его вершинами. Гарантируется, что в графе нет циклов отрицательного веса.
e-olymp 976. Флойд — существование
Дан ориентированный взвешенный граф. По его матрице смежности необходимо для каждой пары вершин определить, существует кратчайший путь между ними или нет.
Кратчайший путь может не существовать по двум причинам:
- Нет ни одного пути.
- Есть путь сколь угодно маленького веса
Первая задача решается Алгоритмом Флойда-Уоршела. Поскольку отрицательных ребер в графе нет, и просят вывести кратчайший путь к каждой из вершин, то надо было всего лишь определить, что мы возьмем за бесконечность. Я выбрал [latex]10001[/latex], поскольку максимальное количество вершин [latex]100[/latex], а вес ребер не превышает [latex]100[/latex], соответственной максимально возможное расстояние не превосходит [latex]100*100 = 10000[/latex].
Во второй задаче была та же идея, но в данной ситуация у нас были ребра отрицательного веса. И у нас появилась проблема, могли существовать циклы отрицательной длины(с каждым проходом расстояние до вершин уменьшалось). Поскольку мы пользовались [latex]while[/latex] -ом, мы зацикливались. По этому необходимо было прекращать добавлять вершины, которую имеют отрицательную индексацию и порогом выбрано [latex]-102[/latex], поскольку цикл мог содержать отрицательные ребра, но при это быть положительным, по этому [latex]<0[/latex] нам не подошло. Дальше необходимо было вывести матрицу существования, методом [latex]way[/latex] мы выходили из вершины и определяли индексацию, пуская из всех вершин, мы можем построково выводить матрицу, только необходимо восстанавливать к исходному виду сам граф. В выводе мы определяли, существует путь и мал ли он. Существование проверялось тем, что эта вершина была посещена, а путь к вершине проверялся по индексу, если он меньше половины порога остановки[latex](-50)[/latex], то путь к этой вершине бесконечен.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
#include <iostream> #include <vector> #include <deque> using namespace std; struct vertax{ // структура вершина int vert, index, father; bool visited; vertax(int a){vert = a; index = 10001; father = a;visited = false;} vertax(int a, int b){ vert = a; father = b; index = 10001;visited = false; } vertax(int a, int b, int x){ vert = a; father = b; index = x;visited = false; } vector<vertax> follow;// с кем связанна эта вершина ~vertax(){} }; struct graph{ vector<vertax> v; // list of vertax int count; graph(){}; graph(int n){ count = n; } void get(){//инициализируем граф for(int i = 1; i <= count; i++){ vertax v(i); for(int j = 1; j <= count; j++){ int x; cin >> x; if(x != 0){ vertax temp(j, i, x); v.follow.push_back(temp); } } graph::v.push_back(v); } } void write(){//вывод вершины, и с кем она связанна for(int i = 0; i < count; i++){ cout << v[i].index << ":"; for(int j = 0; j < v[i].follow.size(); j++){ cout << v[i].follow[j].vert << " "; } cout << endl; } } void way(vertax& x){//алгоритм deque<vertax> list; x.index = 0; x.visited = true; list.push_front(x); while(!list.empty()){ vertax& y = list[0]; for(int i = 0; i < y.follow.size();i++){ v[y.follow[i].vert -1].visited = true; if(v[y.follow[i].vert-1].index > y.index+y.follow[i].index){ v[y.follow[i].vert-1].index = y.index+y.follow[i].index; if(v[y.follow[i].vert-1].index > -102){ list.push_back(v[y.follow[i].vert-1]); } } } list.pop_front(); } } void def(){//фунция к приведению значений по умолчанию for(int i = 0; i < v.size(); i++){ v[i].index = 10001; v[i].visited = false; } } void task1(){ // Решение задачи e-olymp.com №976: Флойд - существование for(int i = 0; i < v.size(); i++){ way(v[i]); for(int j = 0; j < v.size()-1; j++){ if(!v[j].visited){ cout << 0 << " "; }else if(v[j].index < -50){ cout << 2 << " "; }else{ cout << 1 << " "; } } if(!v[v.size()-1].visited){ cout << 0 ; }else if(v[v.size()-1].index < -50){ cout << 2 ; }else{ cout << 1 ; } def(); cout << endl; } } void task2(){ // Решение задачи e-olymp.com №974: Флойд-1 for(int i = 0; i < v.size(); i++){ way(v[i]); for(int j = 0; j < v.size()-1; j++){ if(!v[j].visited){ cout << 0 << " "; }else{ cout << v[j].index << " "; } } if(!v[v.size()-1].visited){ cout << 0 ; }else{ cout << v[v.size()-1].index; } def(); cout << endl; } } }; int main() { ios::sync_with_stdio(false); int n; cin >> n; graph dog(n); dog.get(); dog.task1();// Решаем задачу №976: Флойд - существование dog.task2();// Решаем задачу №974: Флойд-1 return 0; } |