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).
Related
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.
Given a undirected and connected graph G, find a spanning tree whose diameter is the minimum.
singhsumit linked the relevant paper by Hassin and Tamir, entitled "On the minimum diameter spanning tree problem", but his answer is currently deleted. The main idea from the paper is that finding a minimum diameter spanning tree in an undirected graph can be accomplished by finding the "absolute 1-center" of the graph and returning a shortest path tree rooted there.
The absolute 1-center is the point, either on a vertex or an edge, from which the distance to the furthest vertex is minimum. This can be found via an algorithm of Kariv and Hakimi (An Algorithmic Approach to Network Location Problems. I: the p-Centers) or an earlier algorithm of Hakimi, Schmeichel, and Pierce (On p-Centers in Networks), which I will attempt to reconstruct from just the running time and decades of hindsight. (Stupid pay walls.)
Use Floyd--Warshall or Johnson's algorithm to compute all-pairs distances. For each edge u--v, find the best candidate for a 1-center on that edge as follows.
Let the points on the edge u--v be indexed by µ ranging from 0 (u itself) to len(u--v) (v itself). The distance from the point at index µ to a vertex w is
min(µ + d(u, w), len(u--v) - µ + d(v, w)).
As a function of µ, this quantity is increasing and then decreasing, with the maximum at
µ = (len(u--v) + d(v, w) - d(u, w))/2.
Sort the vertices by this argmax. For each partition of the array into a left subarray and a right subarray, compute the interval [a, b] of µ that induce the same argmax partition. Intersect this interval to [0, len(u--v)]; if the intersection is empty, then move on. Otherwise, find the maximum distance L in the left subarray from the point on u--v indexed by a, and the maximum distance R in the right subarray from the point on u--v indexed by b. (The cost of computing these maximums can be amortized to O(1) for each partition, by scanning left-to-right and right-to-left at the beginning.) The best choice is the µ in [a, b] that minimizes max(L - (µ - a), R + (b - µ)).
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.
I am studying algorithms, and I have seen an exercise like this
I can overcome this problem with exponential time but. I don't know how to prove this linear time O(E+V)
I will appreciate any help.
Let G be the graph where the minimum spanning tree T is embedded; let A and B be the two trees remaining after (u,v) is removed from T.
Premise P: Select minimum weight edge (x,y) from G - (u,v) that reconnects A and B. Then T' = A + B + (x,y) is a MST of G - (u,v).
Proof of P: It's obvious that T' is a tree. Suppose it were not minimum. Then there would be a MST - call it M - of smaller weight. And either M contains (x,y), or it doesn't.
If M contains (x,y), then it must have the form A' + B' + (x,y) where A' and B' are minimum weight trees that span the same vertices as A and B. These can't have weight smaller than A and B, otherwise T would not have been an MST. So M is not smaller than T' after all, a contradiction; M can't exist.
If M does not contain (x,y), then there is some other path P from x to y in M. One or more edges of P pass from a vertex in A to another in B. Call such an edge c. Now, c has weight at least that of (x,y), else we would have picked it instead of (x,y) to form T'. Note P+(x,y) is a cycle. Consequently, M - c + (x,y) is also a spanning tree. If c were of greater weight than (x,y) then this new tree would have smaller weight than M. This contradicts the assumption that M is a MST. Again M can't exist.
Since in either case, M can't exist, T' must be a MST. QED
Algorithm
Traverse A and color all its vertices Red. Similarly label B's vertices Blue. Now traverse the edge list of G - (u,v) to find a minimum weight edge connecting a Red vertex with a Blue. The new MST is this edge plus A and B.
When you remove one of the edges then the MST breaks into two parts, lets call them a and b, so what you can do is iterate over all vertices from the part a and look for all adjacent edges, if any of the edges forms a link between the part a and part b you have found the new MST.
Pseudocode :
for(all vertices in part a){
u = current vertex;
for(all adjacent edges of u){
v = adjacent vertex of u for the current edge
if(u and v belong to different part of the MST) found new MST;
}
}
Complexity is O(V + E)
Note : You can keep a simple array to check if vertex is in part a of the MST or part b.
Also note that in order to get the O(V + E) complexity, you need to have an adjacency list representation of the graph.
Let's say you have graph G' after removing the edge. G' consists have two connected components.
Let each node in the graph have a componentID. Set the componentID for all the nodes based on which component they belong to. This can be done with a simple BFS for example on G'. This is an O(V) operation as G' only has V nodes and V-2 edges.
Once all the nodes have been flagged, iterate over all unused edges and find the one with the least weight that connects the two components (componentIDs of the two nodes will be different). This is an O(E) operation.
Thus the total runtime is O(V+E).
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).