Given G=(V,E) be a connected, undirected graph.
Is there a way to converted it to directed graph in both directions between two edges.
so if there is A and B as vertex, then A->B and B->A should exist in directed graph.
I want to know algorithm for it, so I can write a code for it. I am not able to think of it.
A fast way to represent a graph with 10 nodes: representing the adjacency list of a node as a set.
set<int> G[10];
Then, just do
for(int u = 0; u < 10; u++){ //for each node u
for(int v : G[u]){ //for each node v where exists an edge (u → v)
if(!G[v].contains(u)) G[v].insert(u); //add the missing edge (v → u)
}
}
Complexity: O(V + E lg(V))
If you want, you can use unordered_set instead of set and make the complexity O(V + E).
Related
I am trying to design an algorithm where, given a connected weighted graph G = (V, E) and a subset of vertices U that is in V, will construct a minimum spanning tree such that all vertices in U are leaves (other vertices may also be leaves), or returns that no such tree exists (False).
This is all I got, adapting Prim's algorithm (fair warning, its really bad; don't even know if it works/is efficient or what data structures to use, I will accept literally any other correct algorithm instead):
Let x be an arbitrary node in G
Set S = {x}
While S != V:
Let (u,v) be the cheapest edge with u in S and v not in S
Add (u,v) to tree T if u is not in U, add v to S
If all u in U is in the tree T:
return T
Else:
return False
I also have a picture of what I think it would do to this graph I drew:
pic here
A proof that the algorithm is correct would also give me some peace of mind.
If all vertices u ∈ U are to be leaves in a solution, no u can be used in that solution to connect two other vertices. All vertices not in U must be connected by edges not incident to any u.
Remove U and all edges incident to U. Find the minimum spanning tree, then connect each u to the tree by the smallest-weighted edge available from those we removed.
It is given an undirected graph G = (V, E). First it is asked what is the cost of MST.
I can easily find out using Kruskall algorithm, like this:
G = (V, E)
for each edge (u, v) in E sorted by wight
{
if(Find(u) != Find(v))
{
Add (u, v) to the MST
Union(u, v); // put u and v in the same set
}
}
After that, for each edge in the initial graph, it is asked what will the cost of new MST it that edge shall be present in the Minimum Spanning Tree.
If an edge is already present in the MST, the answer remains the same. Otherwise, I can run Kruskall once again. The pseudocode is the following:
G = (V, E)
G1 = runKruskall(G)
for each edge (u, v) in E
{
ClearUnionSets()
if (u, v) in G1
{
print costOf(G1)
} else {
Union(u, v)
G2 = runKruskall(G)
print costOf(G2)
}
}
The problem with that approach is that the total complexity would be: O(E*E)
My question is if there exist a better solution for updating MST as described above.
What I was thinking is that when running for the first time Kruskall, for every edge (u, v), were u and v are in the same set, find the the maximum weighted edge already present in the partial MST that makes a cycle with (u, v) and store that information in a matrix M at M[u][v]. Doing this, the problem of updating MST when a edge becomes mandatory would be solved in O(1).
Can anyone help me with this?
For every edge u-v that is not on the MST, the smallest spanning tree including the edge is the one where u-v replaces the largest edge on the path from u to v on the MST.
The edge to be replaced can be found efficiently as follows. First, root the MST at an arbitrary vertex. We will modify the algorithm to find the lowest common ancestor (LCA) of two vertices, described here. In addition to storing the 2^i th parent for each vertex, we will also store the largest edge on the path to the 2^i th parent. Using this array, while we calculate the LCA we will also calculate the largest edge on the path to the LCA, which gives us the largest edge on the path between the two vertices.
Preprocessing involves finding the MST in O(E log E) and building the parent table for LCA in O(N log N), with the requirement of O(N log N) space. After this, finding the modified MST for each edge requires only the evaluation of LCA once, which can be performed in O(log N). Thus the total complexity is only O(E log E).
The problem is
Given a graph and N sets of vertices, how to check that if the vertices
in each set exist on a path (that may not have to be simple) in the
graph.
For example, if a set of vertices is {A, B, C}
1) On a graph
A --> B --> C
The vertices A, B and C are on a path
2) On a graph
A ---> B ---> ...
^
C -----+
The vertices A, B and C are not on a path
3) On a graph
A <--- B <--- ...
|
C <----+
The vertices A, B and C are not on a path
4) On a graph
A ---> X -----> B ---> C --> ...
| ^
+---------------+
The vertices A, B and C are on a path
Here is a simple algorithm with complexity N * (V + E).
for each set S of vertices with more than 1 elements {
initialize M that maps a vertice to another vertice it reaches;
mark all vertices of G unvisited;
pick and remove a vertex v from S;
while S is not empty {
from all unvisited node, find one vertex v' in S that v can reach;
if v' does not exist {
pick and remove a vertex v from S;
continue;
}
M[v] = v';
remove v' from S;
v = v';
}
// Check that the relations in M forms a path
{
if size[M] != size(S)-1 {
return false;
}
take the vertex v in S that is not in M
while M is not empty {
if not exist v' s.t. M[v]' = v {
return false;
}
}
return true;
}
}
The for-loop takes N step; the while-loop would visit all node/edge in the worst case with cost V + E.
Is there any known algorithm to solve the problem?
If a graph is DAG, could we have a better solution?
Thank you
Acyclicity here is not a meaningful assumption, since we can merge each strong component into one vertex. The paths are a red herring too; with a bunch of two-node paths, we're essentially making a bunch of reachability queries in a DAG. Doing this faster than O(n2) is thought to be a hard problem: https://cstheory.stackexchange.com/questions/25298/dag-reachability-with-on-log-n-space-and-olog-n-time-queries .
You should check out the Floyd-Warshall algorithm. It will give you the lengths of the shortest path between all pairs of vertices in the graph in O(V3). Once you have those results, you can do a brute-force depth-first traversal to determine whether you can go from one node to the next and the next etc. That should happen in O(nn) where n is the number of vertices in your current set. Total complexity, then, should be O(V3 + N*nn) (or something like that).
The nn seems daunting, but if n is small compared to V it won't be a big deal in practice.
I can guess that one could improve on that given certain restrictions on the graph.
I have to implement Prim's algorithm using a min-heap based priority queue. If my graph contained the vertices A, B, C, and D with the below undirected adjacency list... [it is sorted as (vertex name, weight to adjacent vertex)]
A -> B,4 -> D,3
B -> A,4 -> C,1 -> D,7
C -> B,1
D -> B,7 -> A,3
Rough Graph:
A-4-B-1-C
| /
3 7
| /
D
What would the priority queue look like? I have no idea what I should put into it. Should I put everything? Should I put just A B C and D. I have no clue and I would really like an answer.
Prim's: grow the tree by adding the edge of min weight with exactly one end in the tree.
The PQ contains the edges with one end in the tree.
Start with vertex 0 added to tree and add all vertices connected to 0 into the PQ.
DeleteMin() will give you the min weight edge (v, w), you add it to the MST and add all vertices connected to w into the PQ.
is this enough to get you started?
---
so, in your example, the in the first iteration, the MST will contain vertex A, and the PQ will contain the 2 edges going out from A:
A-4-B
A-3-D
Here's prim's algorithm:
Choose a node.
Mark it as visited.
Place all edges from this node into a priority queue (sorted to give smallest weights first).
While queue not empty:
pop edge from queue
if both ends are visited, continue
add this edge to your minimum spanning tree
add all edges coming out of the node that hasn't been visited to the queue
mark that node as visited
So to answer your question, you put the edges in from one node.
If you put all of the edges into the priority queue, you've got Kruskal's algorithm, which is also used for minimum spanning trees.
It depends on how you represent your graph as to what the running time is. Adjacency lists make the complexity O(E log E) for Kruskal's and Prim's is O(E log V) unless you use a fibonacci heap, in which case you can achieve O(E + V log V).
You can assign weights to your vertices. Then use priority queue based on these weights. This is a reference from the wiki: http://en.wikipedia.org/wiki/Prim's_algorithm
MST-PRIM (G, w, r) {
for each u ∈ G.V
u.key = ∞
u.parent = NIL
r.key = 0
Q = G.V
while (Q ≠ ø)
u = Extract-Min(Q)
for each v ∈ G.Adj[u]
if (v ∈ Q) and w(u,v) < v.key
v.parent = u
v.key = w(u,v)
}
Q will be your priority queue. You can use struct to hold the information of the vertices.
(This is derived from a recently completed programming contest)
You are given G, a connected graph with N nodes and N-1 edges.
(Notice that this implies G forms a tree.)
Each edge of G is directed. (not necessarily upward to any root)
For each vertex v of G it is possible to invert zero or more edges such that there is a directed path from every other vertex w to v. Let the minimum possible number of edge inversions to achieve this be f(v).
By what linear or loglinear algorithm can we determine the subset of vertexes that have the minimal overall f(v) (including the value of f(v) of those vertexes)?
For example consider the 4 vertex graph with these edges:
A<--B
C<--B
D<--B
The value of f(A) = 2, f(B) = 3, f(C) = 2 and f(D) = 2...
..so therefore the desired output is {A,C,D} and 2
(note we only need to calculate the f(v) of vertexes that have a minimal f(v) - not all of them)
Code:
For posterity here is the code of solution:
int main()
{
struct Edge
{
bool fwd;
int dest;
};
int n;
cin >> n;
vector<vector<Edge>> V(n+1);
rep(i, n-1)
{
int src, dest;
scanf("%d %d", &src, &dest);
V[src].push_back(Edge{true, dest});
V[dest].push_back(Edge{false, src});
}
vector<int> F(n+1, -1);
vector<bool> done(n+1, false);
vector<int> todo;
todo.push_back(1);
done[1] = true;
F[1] = 0;
while (!todo.empty())
{
int next = todo.back();
todo.pop_back();
for (Edge e : V[next])
{
if (done[e.dest])
continue;
if (!e.fwd)
F[1]++;
done[e.dest] = true;
todo.push_back(e.dest);
}
}
todo.push_back(1);
while (!todo.empty())
{
int next = todo.back();
todo.pop_back();
for (Edge e : V[next])
{
if (F[e.dest] != -1)
continue;
if (e.fwd)
F[e.dest] = F[next] + 1;
else
F[e.dest] = F[next] - 1;
todo.push_back(e.dest);
}
}
int minf = INT_MAX;
rep(i,1,n)
chmin(minf, F[i]);
cout << minf << endl;
rep(i,1,n)
if (F[i] == minf)
cout << i << " ";
cout << endl;
}
I think that the following algorithm works correctly, and it certainly works in linear time.
The motivation for this algorithm is the following. Let's suppose that you already know the value of f(v) for some single node v. Now, consider any node u adjacent to v. If we want to compute the value of f(u), we can reuse some of the information from f(v) in order to compute it. Note that in order to get from any node w in the graph to u, one of two cases must happen:
That path passes through the edge connecting u and v. In that case, the way that we get from w to u is to go from w to v, then to follow the edge from v to u.
That path does not pass through the edge connecting u and v. In that case, the way that we get from w to u is the exact same way that we got from w to v, except that we stop as soon as we get to u.
The reason that this observation is important is that it means that if we know the number of edges we'd flip to get from any node to v, we can easily modify it to get the set of edges that we'd flip to get from any node to u. Specifically, it's going to be the same set of edges as before, except that we want to direct the edge connecting u and v so that it connects v to u rather than the other way around.
If the edge from u to v is initially directed (u, v), then we have to flip all the normal edges we flipped to get every node pointing at v, plus one more edge to get v pointed back at u. Thus f(u) = f(v) + 1. Otherwise, if the edge is originally directed (v, u), then the set of edges that we'd flip would be the same as before (pointing everything at v), except that we wouldn't flip the edge (v, u). Thus f(u) = f(v) - 1.
Consequently, once we know the value of f for a single node v, we can compute it for each adjacent node u as follows:
f(u) = f(v) + 1 if (u, v) is an edge.
f(u) = f(v) - 1 otherwise
This means that we can compute f(v) for all nodes v as follows:
Compute f(v) for some initial node v, chosen arbitrarily.
Do a DFS starting from v. When reaching a node u, compute its f score using the above logic.
All that's left to do is to compute f(v) for some initial node. To do this, we can run a DFS from v outward. Every time we see an edge pointed the wrong way, we have to flip it. Thus the initial value of f(v) is given by the number of wrong-pointing edges we find during the initial DFS.
We thus can compute the f score for each node in O(n) time by doing an initial DFS to compute f(v) for the initial node, then a secondary DFS to compute f(u) for each other node u. You can then for-loop over each of the n f-scores to find the minimum score, then do one more loop to find all values with that f-score. Each of these steps takes O(n) time, so the overall algorithm takes O(n) time as well.
Hope this helps! This was an awesome problem!