Note: The question is entirely changed.
In the following graph, we can traverse entire graph if we select the nodes 0 and 2. I am looking for an efficient algorithm which returns this two nodes. Note that this is neither vertex-cover problem nor dominating-set problem since we don't need to select node 3. We say that, if we select node 0, we can go to node 1 from there and if we select node 2, we can go to node 3 and then node 4 from there.
If I run a SCC algorithm on it, it finds all vertices as a different SCC and I can't go from there to anywhere:
C:\>project2 ../../input.txt o.txt
Following are strongly connected components in given graph (Each line is a different SCC)
2
4
3
0
1
If there is no cycle in the graph i.e. the graph is a Directed Acyclic Graph (DAG), then we just need to count the indegrees for each node. The set of nodes with indegree 0 is the required set.
In case you are not familiar with indegree, if there is an edge a->b then indegree of b increases by 1.
This works because, if there is an edge a->b i.e. b has an indegree it means there is a node a from which b is reachable. So it is always better to include node a to the set instead of b. A node with indegree 0 has no other way to get visited unless we start with the node itself. So it will be included in the set.
In case there is a cycle in the graph, we search for Strongly Connected Components(SCC). Then we have build a new graph considering a SCC as one node and add edges from initial graph which connect two different SCC's. The new graph will be a DAG. Then we can apply the above procedure to find the required set of nodes.
Related
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
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.
I want to create a graph with nodes and edges, where each node will contain n number of values. We would be given with the n values of the starting node, from which we need to generate other nodes where each value in each node would be of the form either:
t_n=t_(n-1)+2
or
t_n=t_(n-1)-1
When such a node is generated, it should create an edge from the old node to the new node.
I know this might be very trivial job, but I have very limited programming knowledge. I have been suggested to use classes in C++ or structure to represent the nodes. Please help me in creating the graph with nodes that would have multiple values and further the next nodes would be generated from the parent node following the above rule. Some C++ code would be very helpful.
Thanks in Advance.
here you have some code but I don't really fully understand your task.
- graph with nodes and edges
- each node has n number of values
- we are given n values of the starting point
- need to generate other nodes where each value in each node would be either
- t_n=t_(n-1)+2
- t_n=t_(n-1)-1
- when such node is generated, it creates an edge from the old node to the new node.
this starting point: do we have to generate a graph from it? what is with the creation of the edge from the old node and the new node? is old node here the starting point?
does n number of values means to where the point is connected to (as a chain of the other edges to which this edge is connected to)? example we are provided a node with a chain of numbers (6, 4, 5) where this means we need to generate extra edges which would be connected x times (first one linked to our starting point would be linked to 6 edges, one of them being the starting point)
will edit my answer when I have more information. could you please draw an example in paint and upload it online and provide the link? it would be easier to imagine.
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> >
I am trying to write a program using a directed graph (which I know about but have never implemented) to simulate a network of transportation.
The user will input a planet name followed by an integer representing the number of total nodes in the graph. The user will then go through each node one by one. They will give it a name give the number of neighbors that node has and then the specific names. The input will look like this.
some_planet 4
node1 2 node2 node3
node2 1 node4
node3 1 node4
node4 1 node1
I then just output which nodes node1 cannot reach. However, I have some questions about implementing this.
1) The big one is storing this stuff. What is an easy way? I thinking about a LinkedList and thought I would link the locations. Then I could pop pointers onto them corresponding to whatever the input is. However, I have no idea how to do the last part.
2) The next big one is searching the graph. I was planning on a recursive depth-first-search . Is there anything wrong with this algorithm that you see? I need to search for every node individually this way though so I will have to increment this. Can I just throw everything in a for loop?
recursive-d-first-search(graph G, node start, node find)
if(start == find)
return true;
else
for every neighbor n of start
success = recursive-d-first-search(graph G, node n, node find);
if(success)
return true;
return false;
I think you just need to use adjacency matrix to store whole graph's connection relation.
in your case, it should be like:
1 2 3 4
1 0 1 1 0
2 0 0 0 1
3 0 0 0 1
4 1 0 0 0
If you use adjacency matrix, I think the breadth-first search may be a good choice, because it's easy to understand and implement. Meanwhile, you need one queue to store next nodes to be checked, and one list to store which nodes have already been checked
For example, you want to check which nodes node1 cannot reach, you just check row 1 and see that it has 2 and 3, and put 2 and 3 to queue. Then check row 2 to see that it has 4, put 2 to list, and put 4 to queue. Then just use a for loop to do the same operation.
In the end, you just need to check which nodes are not in list.
You can also use Boost::Graph if you don't feel like reinventing the wheel...