Finding cycles in a directed graph implemented using an unordered multimap - c++

So, I've implemented a directed graph using an unordered multimap. Each pair within the map is made up of two strings: the vertex and its adjacent vertex.
Now, I am trying to determine if my graph has a cycle, and if so, how big is the cycle. This is the code I have so far:
int findCycle(const unordered_multimap<string,string> & connectedURLVertices, string y, string key)
{
string position;
position=y.find(key);
if(position!=string::npos)
{
return 1;
}
auto nodesToCheck=connectedURLVertices.equal_range(key);
for(auto & node : nodesToCheck)
{
int z=findCycle(connectedURLVertices,y+key,node);
}
}
I've walked through the code on paper and it seems to be logically correct, but I would appreciate it if anyone could take a look and see if I am on the right track or missing anything. Thanks!

To search for cycles in a graph you have to descend recursively through the arcs from some initial node until you reach one already visited node (you can construct a std::set of already visited nodes or mark the nodes as you visit them) or exhaust all the nodes without getting one already visited (absence of cycles) The criterion to select the arc can be adjusted to find it more quickly or the kind of search (first in depth, search by level, etc.)

Related

Adjacency List Representation in Topological Sort

I saw the following implementation of topological sort using DFS on Leetcode https://leetcode.com/problems/course-schedule/discuss/58509/18-22-lines-C++-BFSDFS-Solutions
Now the part of this that is confusing me is the representation of the directed graph which is used for the top sort. The graph is created as follows:
vector<unordered_set<int>> make_graph(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> graph(numCourses);
for (auto pre : prerequisites)
graph[pre.second].insert(pre.first);
return graph;
}
What is confusing me is this line:
graph[pre.second].insert(pre.first);
Presumably the graph is being represented as an adjacency list; if so why is each node being represented by the incoming edges and not the outgoing edges? Interestingly, if I flip pre.second and pre.first like this:
graph[pre.first].insert(pre.second);
The top sort still works. However, it seems most implementations of the same problem use the former method. Does this generalize to all directed graphs? I was taught in my undergraduate degree that a directed graph's adjacency list should contain a list of each nodes outgoing nodes. Is the choice of incoming vs outgoing node arbitrary for the representation of the adjacency list?
To the specific problem which only requires answering true or false, it doesn't matter if you flip every edge. That's because a graph is topological sortable if and only if it has no loops. But if you want an order of taking, it doesn't work as you can see in the different results of [[0, 1]] and [[1, 0]].
Which way to save the graph depends on how you solve the problem. In this given case, we need to know the indegrees of every node (course) and also to update it every time we delete a node from the graph (take the course), so that we know if we can delete a node (we can do it when the indegree is 0). When updating, we minus 1 to each node that the deleted node direct to. If you apply this method (as most do), it's clear how you should save the graph

Find all possible paths in depth first search in graph

I am trying to find all the possible paths from one node in my graph that will visit all other nodes in the graph. I want the function to produce all possibilities of paths in my n*m graph. Each node in my graph has a vector of all neighbors nodes and a Boolean that check if the node is visited or not.
example:
a b
c d
will produce:
abcd
abdc
acbd
...
I tried the solution in this answer, but only return one path. How can I produce all possible paths?
It seems like in some situations by your description you could have infinite paths and a path of infinite length because you didn't specify that nodes couldn't be revisited.
You should implement depth first search and pass a reference to an array of marked (visited) nodes in your recursive DFS method assuming that you have a count of the number of nodes in your graph. After you visit each node, before you leave that node make sure you set it to false again so that it can be reaccessed via another node.
The implementation of this algorithm is really going to depend on how you implemented your graph structure and without the details all I can do is speculate that you have a linked structure with an adjacency list representing the different nodes. I also have no idea how the different nodes map to characters so that is another detail I have to speculate, but say that the nodes are represented by integers.
You need to pass into a DFS method the following: array of marked nodes, a linked list which contains the path information, starting node, (i.e, current node) and final node
void printAllPaths(LinkedList<Integer> currentPath, boolean[] marked, int current, int last){
for( all nodes adjacent to current, node ){
if(node == last){
currentPath.addLast(last);
System.out.println(currentPath);
currentPath.removeLast();
}else if(!marked[node]){
currentPath.addLast(node);
marked[node] = true;
printAllPaths(currentPath, marked, node, final);
marked[node] = false;
currentPath.removeLast();
}
}
}
This will be the basic idea of the code. I apologize if it doesn't compile in advance, but this should print out all of the paths.

What if the root of a tree is changed?

Given a tree(By tree , I mean N Nodes , N-1 edges and it is connected) the root of tree is changed to lets say r. Now given another node lets say t , you have to find the sum of all nodes in the subtree rooted at t.
I was trying to implement it in c++ .
std::map<int, std::vector< pair<int,int> > > map;
if I iterate over the vector map[t] , I have to ensure that it does not go to a path which leads to r . How would I ensure that ?
Also is there a better way to store a tree in c++ , given the conditions that the root of the tree might change ? I think there will be because the map does not convey anything about a root . :)
The problem is that you have your tree stored as a general graph. Hence for a given vertex you don't know which is the arc leading towards the root (i.e. the parent).
The solution very much depends on the context. A simple solution would be a depth first search starting from r and looking for t. As soon as you find t you have found also the parent of t, and you can easily identify the subtree starting from t.
Alternatively you can start from t and look for r. When you find r you have found the parent of t and you can traverse all other arcs to find the subtree of t.
About an alternative representation of the graph, usually it is better to keep a list of vertices and for each vertex keep a list of neighbour vertices as in:
std::map<int, std::list<int> >

Convert array to nodes

Let me start off with saying that I have very basic knowledge of nodes and graphs.
My goal is to make a solver for a maze which is stored as an array. I know exactly how to implement the algorithm for solving (I'm actually implementing a couple of them) but what my problem is, is that I am very confused on how to implement the nodes that the solver will use in each empty cell.
Here is an example array:
char maze[5][9] =
"#########",
"# # #",
"# ## ## #",
"# # #",
"#########"
My solver starts at the top left and the solution (exit) is at the bottom right.
I've read up on how nodes work and how graphs are implemented, so here is how I think I need to make this:
Starting point will become a node
Each node will have as property the column and the row number
Each node will also have as property the visited state
Visited state can be visited, visited and leads to dead end, not visited
Every time a node gets visited, every directly adjacent, empty and not visited cell becomes the visited node's child
Every visited node gets put on top of the solutionPath stack (and marked on the map as '*')
Every node that led to a dead end is removed from the stack (and marked on the map as '~')
Example of finished maze:
"#########",
"#*~#****#",
"#*##*##*#",
"#****~#*#",
"#########"
Basically my question is, am I doing something really stupid here with my way of thinking (since I am really inexperienced with nodes) and if it is could you please explain to me why? Also if possible provide me other websites to check which implement examples of graphs on real world applications so I can get a better grasp of it.
The answer really depends on what you find most important in the problem. If you're searching for efficiency and speed - you're adding way too many nodes. There's no need for so many.
The efficient method
Your solver only needs nodes at the start and end of the path, and at every possible corner on the map. Like this:
"#########",
"#oo#o o#",
"# ## ## #",
"#o oo#o#",
"#########"
There's no real need to test the other places on the map - you'll either HAVE TO walk thru them, or won't have need to even bother testing.
If it helps you - I got a template digraph class that I designed for simple graph representation. It's not very well written, but it's perfect for showing the possible solution.
#include <set>
#include <map>
template <class _nodeType, class _edgeType>
class digraph
{
public:
set<_nodeType> _nodes;
map<pair<unsigned int,unsigned int>,_edgeType> _edges;
};
I use this class to find a path in a tower defence game using the Dijkstra's algorithm. The representation should be sufficient for any other algorithm tho.
Nodes can be of any given type - you'll probably end up using pair<unsigned int, unsigned int>. The _edges connect two _nodes by their position in the set.
The easy to code method
On the other hand - if you're looking for an easy to implement method - you just need to treat every free space in the array as a possible node. And if that's what you're looking for - there's no need for designing a graph, because the array represents the problem in a perfect way.
You don't need dedicated classes to solve it this way.
bool myMap[9][5]; //the array containing the map info. 0 = impassable, 1 = passable
vector<pair<int,int>> route; //the way you need to go
pair<int,int> start = pair<int,int>(1,1); //The route starts at (1,1)
pair<int,int> end = pair<int,int>(7,3); //The road ends at (7,3)
route = findWay(myMap,start,end); //Finding the way with the algorithm you code
Where findWay has a prototype of vector<pair<int,int>> findWay(int[][] map, pair<int,int> begin, pair<int,int> end), and implements the algorithm you desire. Inside the function you'll probably need another two dimensional array of type bool, that indicates which places were tested.
When the algorithm finds a route, you usually have to read it in reverse, but I guess it depends on the algorithm.
In your particular example, myMap would contain:
bool myMap[9][5] = {0,0,0,0,0,0,0,0,0,
0,1,1,0,1,1,1,1,0,
0,1,0,0,1,0,0,1,0,
0,1,1,1,1,1,0,1,0,
0,0,0,0,0,0,0,0,0};
And findWay would return a vector containing (1,1),(1,2),(1,3),(2,3),(3,3),(4,3),(4,2),(4,1),(5,1),(6,1),(7,1),(7,2),(7,3)

C++ recursion for connectivity graph

I haven't implemented anything yet, but I was thinking of using recursion to identify all cells in a grid that are 'actively connected' to a given cell, i.e., cells that are 'active' and directly connected by virtue of sharing a face with the (active) cell in question or more distantly/indirectly connected by sharing a face with one of its (active) neighbors. The disconnections come about because some of the cells in the grid maybe deemed 'inactive' (by whatever definition). My idea/pseudo-code is as follows:
//Call function to traverse connections
traverse_connections(cell);
//Traverse function definition
bool traverse_connections(cell) {
//Check if cell is inactive or traversed - base case
if (current cell is inactive or traversed) {
return true;
}
//-Mark cell then move on to its neighbors
Mark cell as traversed and add it to the list of 'actively connected' cells;
bool ok = true;
for(neighbor_cell in neighbors of cell) {
ok &= traverse_connections(neighbor_cell);
}
return ok;
}
I think this covers the base case, marks the cell, then moves on to do the same for its neighbors, its neighbors' neighbors, and so on. Does this look OK? Are there any obvious gaps I am missing? Would appreciate if anyone with expertise in graph connectivity and recursion can weigh in. I am also having trouble coming up with an iterative equivalent. Any ideas on that would be much appreciated too.
Thanks in advance!
This solution will not work, because it mixes up the concepts of "traversed" and "active/connected". The two are orthogonal: for example, a cell may be inactive and traversed, or active and not traversed. The if statement at the top of your pseudocode returns true for both, which is incorrect.
You should keep a table that marks cells traversed separate from the table that marks cells active. You need to make sure that a cell is marked traversed before going into the recursive call, otherwise the solution may be too slow, or even run out of stack.
Finally, the solution does not need to be recursive: you can accomplish what you need by a straightforward Breadth-first search, which can be done with a queue instead of recursion.
The way you are marking the cells at the moment will most likely cause you problems. For example if one of these cells you are marking has neighbouring cells which need to be traversed later then they may go untraversed.
If you look into the A* (A-Star) algorithm it should give you a good idea of graph traversal. UCS (uniform cost search) is also another algorithm which uses graph traversal.