How to find all the polygonal shapes of given the vertices? - algorithm

I have a list of vertices and I know the connections between them. I am trying to find all the polygonal shapes of the vertices. These polygonal shapes should not overlap.
I did some research and I thought that I could detect the polygonal shapes, if I can traverse over the vertices on clockwise, (or counter-clockwise, doesn’t make a difference).
So, I search for solutions to traverse over the vertices on clockwise. And I found a similar topic and try the suggested solution. But the problem is while traversing over vertices, I cannot decide which path to choose when there are multiple clockwise options.
Basically, I want to find the following polygonal shapes:
* A, E, G, C, D, A
* E, F, G, E
* E, B, F, E
How can I decide to choose G path when I start from A then came to E vertex?
P.S: I am open for a different approach than mine if my approach is not appropriate for this problem or there are better/easier solutions for this

According to your example you are trying to find faces of planar graph, defined by its vertices and edges.
Step 1. Replace each of your un-directed edges by a pair of directed edges (arcs), connecting vertices in both directions. For each arc (v1 -> v2) find a next arc (v2 -> v3), such that both these arcs have the same face to the left of them - this can be done by calculating angles between arcs and the axis (say) OX and ordering them in clockwise (or counter-clockwise) order. Mark all the arcs as "unused".
Step 2. Pick up any "unused" arc and follow next arcs one after another until you reach the origin of the initial arc - you'll get a cycle, bounding a face. You've found a new face with all its arcs/vertices. Mark all the arcs in this cycle as "used". Repeat until there are no "unused" arcs.
Returning to your example - you'll have following arcs:
A -> E, E -> A
A -> D, D -> A
B -> E, E -> B
B -> F, F -> B
C -> D, D -> C
C -> G, G -> C
E -> F, F -> E
E -> G, G -> E
F -> G, G -> F
Examples of next arcs:
(D -> C) is the next arc for (A -> D)
(C -> G) is the next arc for (D -> C)
(G -> E) is the next arc for (C -> G)
and so on...
This algorithm will find all your internal faces plus one external face, bounded by the cycle (A -> E, E -> B, B -> F, F -> G, G -> C, C -> D, D -> A). You can ignore this external face, but in some cases it can be useful - for example, when you're a given a point and you need to find its position relative to your graph as a whole.

Related

Algorithm - Colour surrounded by another colour in a matrix

I recently faced this problem in an interview:
Given below matrix:
[[ R R R R R R],
[ R B B B R R],
[ B R R R B B],
[ R B R R R R]]
Find out if any group of only R's or only B's surrounded by Opposite colour in the 4 directions: up, down, left, right corners.
ex: Answer for the above matrix -> Valid set of B's surrounded by R's in the second row.
[[ R R R R R R],
[ R **B B B** R R],
[ B R R R B B],
[ R B R R R R]]
I tried doing a BFS for a specific colour in all directions but was unable to come up to solution.
Can someone guide me to the solution.
To find the groups of B cells surrounded by R cells, think of the matrix as a graph whose vertices are all the B cells, with edges connecting adjacent B cells. Use BFS (or DFS) to find the connected components of this graph, but ignore the connected components that contain cells on the boundary. Each (non-boundary) connected component contains a set of B cells surrounded by R cells. Then, to find the groups of R cells surrounded by B cells, similarly compute the non-boundary connected components of the graph whose vertices are the R cells.
Since the number of vertices and edges of both graphs is O(mn) and the set of connected components of a graph can be found in time that is linear in the graph's size, the running time of this algorithm is O(mn).

Converting from triangle strip to polygon

I've some areas which contains 1 or more polygons. Each polygon is represented in GL_TRIANGLE_STRIP format, where each vertex is a pair of (lat, long). Is there any way to get the contours of the area?
Some specs:
Contours must be in counter clockwise order.
Any 2 polygons can have one common edge.
Polygons can be concave
A polygon can have maximum 1 'gap' inside of it, which will be represented by another contour, in clockwise order.
I'm looking for an algorithm which complexity is around O(N*logN), where N = number of vertices.
EDIT: I tried solutions like going 2 by 2 until I reach the end of the dataset and then going backwards, but this algorithm works bad on polygons with gaps, for example
this polygon where input is: A B C D E F G H I J, where I = A and J = B, doing that, the output will be A C E G I J H F D B and that should be A C E G and B H F G (order is inverted because it was easier to draw like that).
Another solution was considering points an undirected graph and edges between them (according to GL_TRIANGLE_STRIP format) where I applied a DFS in order to take out connected components. After that I computed the area of each component, and I considered the maximum area polygon as the counter clockwise contour, and the rest as the clockwise contour. That doesn't work because adjacency list requires some sorting which will make the algorithm inefficient.
Another solution I tried was some tweaked convex hull, but a convex hull is still a convex hull and did not work on concave polygons.
I also read about concave hull, but that seems to not give always precise results.
Thank you for your answers!
Let's start by converting a triangle strip to a polygon. We take the following strip as an example:
(Courtesy of Wikimedia Commons)
Your strip definition would be:
A B C D E F
Converting that into a polygon is very simple. Just go through the list and use every second vertex. When you are at the end, return backwards and use the other vertices. In this case:
A C E (reached the end, now return) F D B
This can be done in O(N), where N is the number of vertices of the strip. Whether this is clockwise or counter-clockwise depends on the orientation of the strip.
So, we can turn every strip into a polygon. All that remains is to remove shared edges. Let's say we have two polygons
A C E F D B
W X E C Y Z
Note that any edge that is shared (in this case C E) will appear in opposite directions (C E in the first polygon, E C in the second one). To find the area contour, we simply need to find matching edges and merge the two polygons.
To find matching edges, it is enough to write all the polygon edges into a hash map (store what polygon they belong to and where they are in the polygon). This can be done in O(E), where E is the total number of polygon edges.
To finally merge polygons, it is actually simpler to create new ones. Modification is definitely possible, but a bit more delicate. To do that we just need to walk along our polygon edges. As long as we are on an edge whose inverse is not in the hash map, then write this edge to the output polygon. If it is, ignore it and continue on the other polygon. Mark the edges that you visited and stop as soon as you are back to an edge that you visited before. Do this until all edges are visited (or both directions are in the hash map). This whole process can be done in O(E), where E is the total number of polygon edges.
Here is how that would look like in our example:
Start at polygon 1
Start at edge (A, C)
(A, C) is neither visited nor is its inverse in the hash map
Create new output area = [A, C]
the inverse of (C, E) is in the hash map, continue to polygon 2
(C, Y) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y]
(Y, Z) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z]
(Z, W) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z, W]
(W, X) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z, W, X]
(X, E) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z, W, X, E]
the inverse of (E, C) is in the hash map, continue to polygon 1
(E, F) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z, W, X, E, F]
(F, D) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z, W, X, E, F, D]
(D, B) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z, W, X, E, F, D, B]
(B, A) is neither visited nor is its inverse in the hash map
Append it to the area = [A, C, Y, Z, W, X, E, F, D, B, A]
(A, C) is already visited
Close the area contour, continue to check other unvisited edges
If you want, you can then also group the generated contours by the polygons they were created from to find connected areas that are bounded by multiple contours. A disjoint set over the polygons would be helpful for that task. If you need, you could also try to classify the contours into holes and outer contours. But be aware that this notion is highly ambiguous on the sphere (imagine a sphere and an area that is a band along the equator - which of the two contours is the hole and which is outside?) For comparatively small areas, you could use the area for this classification.

Find the simple path with at least 5 edges in directed graph

I have a question.
Given a directed graph (G = V, E) and the source vertex s from V group.
we want to check whether there is a simple path (no circles) from s to any vertex in G with at least 5 edges.
Offer as efficient an algorithm as possible that solves the problem for a graph G that can contain circles.
please I need your help
Thanks :-)
We need to find any 5-edge simple directed path starting at vertex s. This path will look like:
s -> a -> b -> c -> d -> e (all distinct)
Now let's go through the all possible values of c (any vertex besides s) and then for every c value we can go through all edges that do not contain s and c vertices and for the edge (x, y) do the following:
if edge (s, x) exists and edge (y, c) exists
put (x, y) in AB edges list
if edge (c, x) exists
put (x, y) in DE edges list
This can be done in O(|E|). Then we need to find a pair of edges (E1, E2) such that E1 is in AB, E2 is in DE and they don't share any vertex in common. The latter can be done in O(|E|).
We can take a graph G' = (V, DE) and find the degrees of the vertices. Then for every edge (a, b) from AB we need to check that
degree(a) + degree(b) = |DE| + x
where x = 1 if (a, b) is in DE, otherwise x = 0. If this equality does not hold it means that there is an edge in DE that contains neither a nor b and we can just iterate through entire DE to find the answer.
The overall complexity will be O(|V||E|) with O(|E|) additional memory.

Finding an edge that decreases the shortest path from A to B by the most

Given an undirected graph G with edge weights, a set of candidate edges (length |V| + |E|), and vertices A and B, find the edge that decreases the shortest path from A to B by the most.
For example:
The candidate edges are the dotted lines. The shortest path from A to B is A -> C -> D -> G -> B (cost 7). But with the edge (D, B), the shortest path is A -> C -> D -> B (cost 6), so the algorithm should return (D, B).
I came up with a brute force solution O((|V| + |E|)^2 log |V|):
for each candidate edge:
add the edge to the graph
run Dijkstra's to find the cost of the shortest path from A to B
remove the edge
return the candidate edge that results in the shortest path
but is there anything better?
One approach is:
Run Dijkstra from A and store distance to each node n in A[n]
Run Dijkstra from B and store distance to each node n in B[n]
Loop over each candidate edge. For an edge with weight w that connects vertices x and y, compare w+A[x]+B[y] and w+A[y]+B[x]
The smaller of w+A[x]+B[y] and w+A[y]+B[x] gives the shortest path between A and B when the candidate edge is used.

Finding Edges of a Graph

I want to find the weight of the edges of a graph by using the output of the Prim's algorithm.
Note: In a graph has n edges, each edge is different and between 1-n.
For example:
Vertices = {A, B, C, D, E}
Edges = {B-D, D-E, E-A, C-B, A-D, D-C, A-C}
Extract_Min() Order = B D C A E
By using the information above, I want to find the weight of each edge. Do you have any ideas?
Thanks in advance.
Edit: The solution does not have to be unique.
By your example:
Vertices = {A, B, C, D, E}
Edges = {B-D, D-E, E-A, C-B, A-D, D-C, A-C}
Extract_Min() Order = B D C A E
Look at the order given by Extract_Min().
The edge with weight 1 is surely B-D.
Assign weight 2 to some single edge from the set {B,D} to C.
Assign weight 3 to some single edge from the set {B,D,C} to A.
Assign weight 4 to some single edge from the set {B,D,C,A} to E.
Assign the remaining weights to the remaining edges in any order.

Resources