I have a tree with N nodes and each edge has some weight. I have to find, for all pairs (u,v) 1<=u<=N 1<=V<=N, the maximum weight in the path from U to V. How can I find the total sum of the maximum weight for every pair (U,V)?
You can use Floyd Warshall Algorithm. You can multiply each edges with (-1), and solve your problem like finding the shortest path between all pairs, then multiply your result with (-1).
For every node, you can extend it to a tree. The extend process of node x is, for every edge (x, y), if value[x] > value[y] then we go to node y and continue the process, so the result of extending node x is a tree, and the value of x is the largest of all.
There are possibility that some value of the tree are equal maximum, to break the tie, we can assign each node an index, to make the value like a pair (value[x], idx[x]), and each idx is different.
Then for each extended tree, suppose the node with max value is x, take it as the root, suppose it has m subtree, each has total node number num[i], then every path between two node from different subtree has max weight value[x], so value[x] counts SUM[num[i]*num[j]] (i != j) times, ie. (SUM[num[i]]^2-SUM[num[i]^2])/2, and we miss the path starting from node x, so we should also count SUM[num[i]] more times. num can be generated during the extending process.
This is a O(n^2) solution. And I believe there is other much more faster algorithm.
Given a tree T, let S(T) be the sum you're interested in: the sum over every pair of vertices of the largest weight of an edge in the path between them.
If T has no edges then it has 1 vertex, and S(T) = 0.
Otherwise, consider the largest edge E in the tree, and say its weight is W. If you remove this edge from the tree, you end up with two smaller trees (call them T1 and T2). Let's say T1 is the tree above the edge (that is, the subtree that contains the root of T).
If u is in T1 and v is in T2, then the largest edge in any path between them goes through E, which has weight W and is guaranteed to be the largest weight in the path. Otherwise, if u and v are both in T1, then the path between them stays inside T1. Same for T2.
Thus S(T) = 2*W*v(T1)*v(T2) + S(T1) + S(T2). (where v(T) means the number of vertices of T).
This gives you a recursive formula for computing S(T), and the only difficulty is finding the largest edge quickly in the subproblems.
One way is to store in each vertex of the tree the maximum weight of any edge below that vertex. Then you can find the largest weight in the whole tree in O(log(v(T)) time, and when you, following the algorithm above, remove that largest weight, you can patch up the weights in the part of the tree above the edge in log(v(T1)) time. The weights in T2 don't need adjusting.
Overall, this gives you an O(v(T)log(v(T))) algorithm. Each edge is removed exactly once, and there's at most O(log(v(T))) work per step.
Related
Given a binary tree T with a weight function on its edge set w : E -> Z
(Note the weight can be negative too) and a positive integer k. For
a subset T' of V (T), cost(T') is defined as the sum of the weights of
edges (u, v) such that u, v ∈ T'
.Give an algorithm to find a subset T'
of exactly k vertices that minimizes cost(T').
How to solve this problem using dynamic programming?
It is usually easier to solve dynamic programming problems top down. They are often more efficient if solved bottom up. But I'll just get you going on the easier version.
Fill out this recursive function:
def min_cost(root, count_included, include_root):
# root is the root of the subtree
# count_included is how many nodes in the subtree to include in T'
# include_root is whether root will be in T'.
#
# It will return the minimum cost, or math.inf if no solution exists
...
And with that, your answer will be:
min_cost(root_of_tree, k, True) + min_cost(root_of_tree, k, False)
This is slow, so memoize for the top down.
I will leave the bottom up as a more difficult exercise.
Given a weighed, connected and directed graph G=(V,E) with n vertexes and m edges, and given a pre-calculated shortest path distance's matrix S where S is n*n S(i,j) denotes the weight of shortest path from vertex i to vertex j.
we know just weight of one edge (u, v) is changed (increased or decreased).
for two specific vertex s and t we want to update the shortest path length between these two vertex.
This can be done in O(1).
How is this possible? what is the trick of this answer?
You certainly can for decreases. I assume S will always refer to the old distances. Let l be the new distance between (u, v). Check if
S(s, u) + l + S(v, t) < S(s, t)
if yes then the left hand side is the new optimal distance between s and t.
Increases are impossible. Consider the following graph (edges in red have zero weight):
Suppose m is the minimum weight edge here, except for (u, v) which used to be lower. Now we update (u, v) to some weight l > m. This means we must find m to find the new optimum length.
Suppose we could do this in O(1) time. Then it means we could find the minimum of any array in O(1) time by feeding it into this algorithm after adding (u, v) with weight -BIGNUMBER and then 'updating' it to BIGNUMBER (we can lazily construct the distance matrix because all distances are either 0, inf or just the edge weights). That is clearly not possible, thus we can't solve this problem in O(1) either.
I have seen this problem before for unweighted trees and trees with positive edge weights, but have not seen a solution for trees that could have negative weights.
For reference, the center of a tree is defined as the vertex that minimizes the maximum distance to any other vertex.
It is exactly the same as a dynamic programming solution for a tree with positive edge weights. Let's run depth first search two times(we can pick an arbitrary vertex as a root). During the first phase, we will compute distIn(v) = the longest distance from v to a vertex from the v's subtree. I think this part is trivial(I can elaborate on this if necessary). During the second phase, we will compute the furthest vertex which is not inside the v's subtree for all v. Let's call it distOut(v). Here is a pseudo code for it:
void computeDistOut(v, pathFromParent)
distOut(v) = pathFromParent
childDists = empty list
for c : children of v
childDists.add(distIn(c) + cost(v, c))
for c : children of v
maxDist = max among all distances from childDists except (distIn(c) + cost(v, c))
computeDistOut(c, max(pathFromParent, maxDist) + cost(v, c))
The maximum distance from each vertex is max(distIn(v), distOut(v)). Now we can just pick a vertex that minimizes this value(it is a center by the definition).
About the time complexity: it is linear if this solution is implemented properly. Instead of maintaining a list of distances to all children(childDists in pseudo code), we can just store two maximum values among them. It allows us to get the maxDist value in O(1)(it is either the first or the second maximum).
I couldnt get my head around this question, need help just a direction would be great..
Let there be a rooted directed tree T, not necessarily binary.
There is a weight associated with each vertex, such that the weight of a vertex is greater than the weight of the vertex's parent.
Each vertex can be designated as either a regular or a pivot vertex.
The cost of a pivot vertex is the same as its weight.
Regular vertices get discounts: their cost is their weight minus the weight of the closest ancestor that is a pivot vertex.
Thus, selecting a vertex as a pivot vertex may increase its cost, but it will decrease the costs of some of its descendants.
If a regular vertex has no ancestor which is a pivot vertex, then its cost is its weight itself. There is no limit on the number of pivot vertices.
I have to design an efficient algorithm to designate every vertex as either a regular vertex or a pivot vertex, such that the total cost of all vertices is minimized.
Here's another dynamic program. I'm going to assume that the root must be a pivot node. For each node u, let W[u] be the weight of u. For nodes u and v such that u = v or u is a proper descendant of v, let C[u, v] be the optimum cost of the subtree rooted at u given that u's leafmost pivot ancestor is v. Then we have a recurrence
C[u, u] = W[u] + sum over children t of u of C[t, u];
C[u, v] | u is a proper descendant of v
= (W[u] - W[v]) + sum over children t of u of min(C[t, t], C[t, v]).
There is no separate base case because the sum may be empty. The running time is O(number of descendant-ancestor pairs), which is O(n^2).
You could use dynamic programming where DP[i,k] represents the smallest cost of the subtree rooted at vertex i assuming that looking into the subtree we can see k regular vertices (the concept is that pivot nodes are opaque, while regular nodes are transparent).
When working out the cost we use the normal logic everywhere except these k regular vertices. For the k vertices we assign the cost of the vertex, but have not yet applied the discount.
The point is that when we assign a pivot node above this subtree of weight x, we can instantly calculate the final cost of the subtree by applying k times the discount x.
It is not clear whether this is efficient enough for your case because you have not said how large your graph is.
There will be O(n^2) entries in the dynamic programming table (where n is the number of vertices).
I would expect the recurrence relation to take O(n) to compute, so this will give an overall complexity of O(n^3).
Love some guidance on this problem:
G is a directed acyclic graph. You want to move from vertex c to vertex z. Some edges reduce your profit and some increase your profit. How do you get from c to z while maximizing your profit. What is the time complexity?
Thanks!
The problem has an optimal substructure. To find the longest path from vertex c to vertex z, we first need to find the longest path from c to all the predecessors of z. Each problem of these is another smaller subproblem (longest path from c to a specific predecessor).
Lets denote the predecessors of z as u1,u2,...,uk and dist[z] to be the longest path from c to z then dist[z]=max(dist[ui]+w(ui,z))..
Here is an illustration with 3 predecessors omitting the edge set weights:
So to find the longest path to z we first need to find the longest path to its predecessors and take the maximum over (their values plus their edges weights to z).
This requires whenever we visit a vertex u, all of u's predecessors must have been analyzed and computed.
So the question is: for any vertex u, how to make sure that once we set dist[u], dist[u] will never be changed later on? Put it in another way: how to make sure that we have considered all paths from c to u before considering any edge originating at u?
Since the graph is acyclic, we can guarantee this condition by finding a topological sort over the graph. topological sort is like a chain of vertices where all edges point left to right. So if we are at vertex vi then we have considered all paths leading to vi and have the final value of dist[vi].
The time complexity: topological sort takes O(V+E). In the worst case where z is a leaf and all other vertices point to it, we will visit all the graph edges which gives O(V+E).
Let f(u) be the maximum profit you can get going from c to u in your DAG. Then you want to compute f(z). This can be easily computed in linear time using dynamic programming/topological sorting.
Initialize f(u) = -infinity for every u other than c, and f(c) = 0. Then, proceed computing the values of f in some topological order of your DAG. Thus, as the order is topological, for every incoming edge of the node being computed, the other endpoints are calculated, so just pick the maximum possible value for this node, i.e. f(u) = max(f(v) + cost(v, u)) for each incoming edge (v, u).
Its better to use Topological Sorting instead of Bellman Ford since its DAG.
Source:- http://www.utdallas.edu/~sizheng/CS4349.d/l-notes.d/L17.pdf
EDIT:-
G is a DAG with negative edges.
Some edges reduce your profit and some increase your profit
Edges - increase profit - positive value
Edges - decrease profit -
negative value
After TS, for each vertex U in TS order - relax each outgoing edge.
dist[] = {-INF, -INF, ….}
dist[c] = 0 // source
for every vertex u in topological order
if (u == z) break; // dest vertex
for every adjacent vertex v of u
if (dist[v] < (dist[u] + weight(u, v))) // < for longest path = max profit
dist[v] = dist[u] + weight(u, v)
ans = dist[z];