Here is a very interesting problem which I have encountered: there is a directed tree in which the weight of each node changes with time and I have to find the distance from the root to some node.
Problem Statement:
The expected time to reach the counter from a queue depends on the number of people in that queue plus the number of people in the other queues.
For example, if there are 2 in-queues containing 3 fans each, the leading person from queue1 will be sent in first, followed by the leading person from queue2, followed by next person from queue1 and so on. It’s an alternate pick between the incoming queues.
Full Problem Statement
For a Given Input
Calculate the minimum time for a person to reach the ticket counter who is just about to enter any queue. Also, output the path that he should take to reach the counter in minimum time in the worst case (at each junction point, the policeman starts choosing people from the in-queue other than the one we are calculating the minimum time for).
How can one solve this type of time-varying problem?
For Example:
7
6
1 5 9
2 5 5
3 6 1
4 6 3
5 7 7
6 7 4
Graph Looks Like This:
The distance between two nodes can be obtained in terms of lowest common ancestor. Following is the formula. Dist(n1, n2) = Dist(root, n1) + Dist(root, n2) - 2*Dist(root, lca) 'n1' and 'n2' are the two given keys 'root' is root of given Binary Tree.
This problem can be solved by finding the shortest path from each entry node (leaves) to the exit node (root).
In my implementation below I used an adjacency matrix to represent that kind of (directed) graph, but you can think of it as a binary tree (because the problem defined maximum 2 input queues for each junction).
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
The only difference between a normal shortest path and this problem is that whenever we have two incoming queues, the policeman sends fans from each queue one by one alternatively. Which means that in order to pass that queue it will take double the time +1. The +1 is because we assume that he starts from the longer queue path.
Here is a working C++ code that returns a pair with both the optimal time and its path. In case there are more than one optimal paths it will return only one of them.
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);
}
}
The time complexity of this code is O(n^2)
where n
is the number of vertices. You might also be able to implement it in O(n)
using adjacency list representation (= binary tree).
For completeness, here is also the main
for creating the graph from the given input and printing the optimal time and path. See this live test of your example's input
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With