Минимальное расстояние от листа до корня дерева
Вот очень интересная проблема, с которой я столкнулся: существует ориентированное дерево, в котором вес каждого node изменяется со временем, и мне нужно найти расстояние от корня до некоторого node.
Проблема:
- Theres длинная очередь перед счетчиком билетов. Вот очередь
соображения.
- В точке соединения может быть не более 2 входящих очередей.
- От любой точки соединения может быть только одна исходящая очередь
- Могут быть несколько точек соединения, и очереди перемещаются
уни-направленно
- Будет только один конечный пункт счетчика билетов, на который все
очереди
- Есть несколько точек входа для поклонников, чтобы добраться до
Счетчик
- Мне нужно разработать систему, которая может предложить поклонникам
"Оптимальный путь" и его "Ожидаемое время" для достижения счетчика.
Ожидаемое время достижения счетчика из очереди зависит от количества людей в этой очереди и количества людей в других очередях.
- Время, затраченное на пересечение счетчика билетов и получение билета, равно 1
единица времени
- Предположим, что есть полицейский, стоящий в каждой точке соединения
чья работа заключается в том, чтобы открыть ворота соединения для отправки людей из
в очереди (очереди) в очередь. Если в очереди есть несколько очередей
соединение, полицейский будет отправлять поклонников из каждой очереди один за другим
в качестве альтернативы
Например, если в очереди есть 2 очереди, каждая из которых содержит по 3 вентилятора, то первый человек из очереди будет отправлен первым, за ним следует ведущий человек из очереди2, а затем следующий человек из очереди1 и т.д. Его альтернативный выбор между входящими очередями.
Полное описание проблемы
Для заданного ввода
- Первая строка содержит количество соединений
- Вторая строка содержит количество очередей
- Следующие строки 'e' содержат три значения: начальное соединение, конец
соединение и количество людей в этой очереди. (Это также максимальное количество людей, которые могут стоять в этой очереди.)
Рассчитайте минимальное время для человека, который достигнет счетчика билетов, который вот-вот войдет в любую очередь. Кроме того, выведите путь, который он должен предпринять, чтобы достигнуть счетчика в минимальное время в худшем случае (в каждой точке соединения полицейский начинает выбирать людей из очереди, кроме той, которую мы вычисляем минимальное время для).
Как решить этот тип изменяющейся во времени проблемы?
Пример:
7
6
1 5 9
2 5 5
3 6 1
4 6 3
5 7 7
6 7 4
График выглядит следующим образом:
![введите описание изображения здесь]()
Счетчик счетчика: 7
Точки входа: 1, 2, 3, 4
- Время, требуемое для лица, которое просто входит в очередь от входа
точка 3: 1 человек из очереди (3,6) + 2 человека из очереди (4,6) + 4
люди из очереди (6,7) + 7 человек из очереди (5,7) + 1 человек из
очередь (1,5) будет идти до этого человека.
Оптимальное время = 15
Путь 3 → 6 → 7
Ответы
Ответ 1
Эта проблема может быть решена путем нахождения кратчайшего пути из каждой записи node (слева) до выхода node (root).
В моей реализации ниже я использовал матрицу смежности для представления такого (направленного) графа, но вы можете думать о ней как о бинарном дереве (потому что проблема определила максимум 2 очереди ввода для каждого перехода).
Псевдо-код
int shortestPath(root)
if (both childs exists)
return min(shortestPath(node->left),shortestPath(node->right))*2+1
if (left child exists)
return shortestPath(node->left)
if (right child exists)
return shortestPath(node->right)
return 0; //no childs
Единственное различие между нормальным кратчайшим путем и этой проблемой состоит в том, что всякий раз, когда у нас есть два входящих очереди, полицейский отправляет поклонников из каждой очереди поочередно. Это означает, что для прохождения этой очереди потребуется удвоить время +1. +1 - это потому, что мы предполагаем, что он начинается с более длинного пути очереди.
Код С++
Вот рабочий код на С++, который возвращает пару с оптимальным временем и его контуром. Если существует более одного оптимального пути, он возвращает только один из них.
const pair<int,vector<int>>& min(const pair<int,vector<int>>& a, const pair<int,vector<int>>& b) {
return (a.first < b.first) ? a : b;
}
pair<int,vector<int>> findShortestPath(vector<vector<int>>& graph, int v){
vector<pair<int,vector<int>>> childs;
for (int i=0; i<v; i++){
if (graph[i][v] != -1){
pair<int,vector<int>> path = findShortestPath(graph,i);
path.second.push_back(v+1);
childs.push_back(make_pair(path.first + graph[i][v], path.second));
}
}
if (childs.size() == 2){
pair<int,vector<int>> path = min(childs[0],childs[1]);
return make_pair(path.first*2+1, path.second);
}
if (childs.size() == 1){
return make_pair(childs[0].first,childs[0].second);
}
else{
vector<int> start = {v+1};
return make_pair(0,start);
}
}
временная сложность этого кода O(n^2)
, где n
- количество вершин. Вы также можете реализовать его в O(n)
, используя представление списка смежности (= двоичное дерево).
Для полноты здесь также есть main
для создания графика из данного ввода и печати оптимального времени и пути. Посмотрите это живое испытание вашего примера ввода
int main()
{
int n, e;
cin >> n; //num of vertices
cin >> e; //num of queues
vector<vector<int>> graph;
//initialize graph matrix cells to -1
graph.resize(n);
for (int i=0;i<n;i++){
graph[i].resize(n);
for (int j=0;j<n;j++)
graph[i][j] = -1;
}
//add edges and their weights
for (int i=0;i<e;i++){
int s,d,val;
cin >> s >> d >> val;
graph[s-1][d-1] = val;
}
//run algorithm
pair<int,vector<int>> path = findShortestPath(graph, n-1);
//print results
cout << path.first << endl;
for (int i=0;i<path.second.size()-1;i++)
cout << path.second[i] << " -> ";
cout << path.second[path.second.size()-1] << endl;
return 0;
}
Ответ 2
Это должно решаться динамическим программированием.
Пусть P (j) - позиция человека, если он принимает оптимальный веер, чтобы пройти через точку соединения j. Например, P (6) = 4 в вашем случае, потому что кто-то, прибывающий в точку соединения 3, будет четвертым, чтобы пройти через точку соединения 6 (после P27, P26 и P28).
Следующие три утверждения очевидны и решают проблему.
Если "точка соединения" j является вентилятором, P (j) = 1 (базовый случай)
Если "точка соединения" j является правильной точкой соединения с дочерними l и r, и в очереди между l и j и y люди находятся в очереди между r и j, мы имеем P (j) = 2 * min (P (l) + x, P (r) + y)
Если кто-то, если n'th пройти через счетчик, требуется n-1 раз, чтобы туда добраться.
Вы можете легко найти время с помощью DP и с помощью некоторых книг (если минимум достигнут слева или справа), вы можете получить оптимальный вентилятор.