How do I find all paths in a sequence of edges in a fast way? - algorithm

Let E be a given directed edge set. Suppose it is known that the edges in E can form a directed tree T with all the nodes (except the root node) has only 1 in-degree. The problem is how to efficiently traverse the edge set E, in order to find all the paths in T?
For example, Given a directed edge set E={(1,2),(1,5),(5,6),(1,4),(2,3)}. We know that such a set E can generate a directed tree T with only 1 in-degree (except the root node). Is there any fast method to traverse the edge set E, in order to find all the paths as follows:
Path1 = {(1,2),(2,3)}
Path2 = {(1,4)}
Path3 = {(1,5),(5,6)}
By the way, suppose the number of edges in E is |E|, is there complexity bound to find all the paths?

I have not worked on this kind of problems earlier. So just tried out a simple solution. Check this out.
public class PathFinder
{
private static Dictionary<string, Path> pathsDictionary = new Dictionary<string, Path>();
private static List<Path> newPaths = new List<Path>();
public static Dictionary<string, Path> GetBestPaths(List<Edge> edgesInTree)
{
foreach (var e in edgesInTree)
{
SetNewPathsToAdd(e);
UpdatePaths();
}
return pathsDictionary;
}
private static void SetNewPathsToAdd(Edge currentEdge)
{
newPaths.Clear();
newPaths.Add(new Path(new List<Edge> { currentEdge }));
if (!pathsDictionary.ContainsKey(currentEdge.PathKey()))
{
var pathKeys = pathsDictionary.Keys.Where(c => c.Split(",".ToCharArray())[1] == currentEdge.StartPoint.ToString()).ToList();
pathKeys.ForEach(key => { var newPath = new Path(pathsDictionary[key].ConnectedEdges); newPath.ConnectedEdges.Add(currentEdge); newPaths.Add(newPath); });
pathKeys = pathsDictionary.Keys.Where(c => c.Split(",".ToCharArray())[0] == currentEdge.EndPoint.ToString()).ToList();
pathKeys.ForEach(key => { var newPath = new Path(pathsDictionary[key].ConnectedEdges); newPath.ConnectedEdges.Insert(0, currentEdge); newPaths.Add(newPath); });
}
}
private static void UpdatePaths()
{
Path oldPath = null;
foreach (Path newPath in newPaths)
{
if (!pathsDictionary.ContainsKey(newPath.PathKey()))
pathsDictionary.Add(newPath.PathKey(), newPath);
else
{
oldPath = pathsDictionary[newPath.PathKey()];
if (newPath.PathWeights < oldPath.PathWeights)
pathsDictionary[newPath.PathKey()] = newPath;
}
}
}
}
public static class Extensions
{
public static bool IsNullOrEmpty(this IEnumerable<object> collection) { return collection == null || collection.Count() > 0; }
public static string PathKey(this ILine line) { return string.Format("{0},{1}", line.StartPoint, line.EndPoint); }
}
public interface ILine
{
int StartPoint { get; }
int EndPoint { get; }
}
public class Edge :ILine
{
public int StartPoint { get; set; }
public int EndPoint { get; set; }
public Edge(int startPoint, int endPoint)
{
this.EndPoint = endPoint;
this.StartPoint = startPoint;
}
}
public class Path :ILine
{
private List<Edge> connectedEdges = new List<Edge>();
public Path(List<Edge> edges) { this.connectedEdges = edges; }
public int StartPoint { get { return this.IsValid ? this.connectedEdges.First().StartPoint : 0; } }
public int EndPoint { get { return this.IsValid ? this.connectedEdges.Last().EndPoint : 0; } }
public bool IsValid { get { return this.EdgeCount > 0; } }
public int EdgeCount { get { return this.connectedEdges.Count; } }
// For now as no weights logics are defined
public int PathWeights { get { return this.EdgeCount; } }
public List<Edge> ConnectedEdges { get { return this.connectedEdges; } }
}

I think DFS(Depth First Search) should suit your requirements. Have a look at it here - Depth First Search - Wikipedia. You can tailor it to print the paths in the format that you require. As regards the complexity, since every node in your tree has in-degree one , the number of edges for your tree is bounded as - |E| = O(|V|). Since DFS operates with a complexity of O(|V|+|E|), your overall complexity comes out to be O(|V|).

I did this question as a part of a my assignment. The gentleman above has correctly pointed out to use pathID. You must visit each edge atleast once hence the complexity bound is O(V+E) but for tree E=O(V) therefore the complexity is O(v). I will give you a glimpse since the details are bit involved -
you will label each path with a unique ID and the path are alloted IDs in the incremental values such as 0,1,2.... A pathID of a path is the sum of weights of the edges on the path. So using DFS allocate weights to the path. You may begin by using 0 for edges until you encounter your first path and then you keep adding 1 and so on. You will also have to argue the correctness and properly allocate the weights. DFS will do the trick.

Related

Unvisited neigbours in graph path

I am trying to find distance in an undirected graph, but when navigating to different path, the count cannot be calculated properly.
I am not sure what is the best approach for:
1) To count the path values excluding unnecessary paths.
2) To keep the path (I think to use LinkedList or ArrayList, etc. what is the best choices for this situation.
Any help would be appreciated.
Here is a code that solves this problem:
void Measure(Node node)
{
path.Add(node);
node.IsVisited = true;
if (node != destination)
{
foreach (var neighbor in node.Neighbors.Where(n=>!n.IsVisited))
{
Measure(neighbor);
}
path.RemoveAt(path.Count - 1);
}
}
You can use any dynamic length structure such as List or LinkedList for storing the path. List is recommended for simplicity.
usage:
var path = new List<Node>()
Measure(firstNode);
Print(path.Count);
this works if there is a path between the two nodes. otherwise the path is empty.
class Node
{
public string Name { get; set; }
public bool IsVisited { get; set; }
public List<Node> Neighbors { get; set; } = new List<Node>();
}

How to find if the distance between destination and source is less than 5?

I am trying to write a method that will return true if the distance between two nodes is less than 5 in a graph. I try to write with the minimum distances algorithm as shown :
class Movie{ //this is the node in the graph
String name;
List<Movie> movies;
}
private static boolean isgoodMovies(Movie origin, Movie destination){
Queue<Movie> nextToVisit = new LinkedList<>();
Set<Movie> visited = new HashSet<>();
HashMap<Movie, Integer> distances = new HashMap<>();
nextToVisit.add(origin);
distances.put(origin, 0);
while (!nextToVisit.isEmpty()){
Movie visitedNode = nextToVisit.remove();
if(visited.equals(destination)) {break;}
if(!visited.contains(visitedNode)) {continue;}
visited.add(visitedNode);
for (Movie movie : visitedNode.movies) {
nextToVisit.add(movie);
distances.put(movie, distances.get(visitedNode) + 1);
}
}
return distances.get(origin) < 5;
}
By modifying the minimum distances algorithm, I return the boolean based on the distance of the origin node. I want to optimize it in a way that I do not use a hashmap or any collection, simply having a distance variable. Do you think it is possible?
You could use the recursion here if the number of movies isn't huge (you can get StackOverflowError if the number of method invocations exceeds the maximum stack depth). So, don't use any Collection except for a HashSet as shown below:
private static boolean isGoodMovies(Movie origin, Movie destination) {
Set<Movie> visited = new HashSet<>();
return isGoodMovies(origin, destination, visited, 0);
}
private static boolean isGoodMovies(Movie current, Movie destination, visited, int depth) {
if (depth >= 5) {
return false;
}
if (destination.equals(current)) {
return true;
}
boolean isGood = false;
for (Movie child : current.movies) {
if (!visited.contains(child) {
visited.add(child);
isGood |= isGoodMovies(child, destination, depth + 1);
}
}
return isGood;
}

Randomised Path on graph - set length, no crossing, no dead ends

I am working on a game with a 8 wide 5 high grid. I have a 'snake' feature which needs to enter the grid and "walk" around for a set distance (20 for example). There are certain restrictions for the movement of the snake:
It needs go over the predetermined amount of blocks (20)
It cannot go over itself or double back (no dead ends)
Currently I am using a Randomised Depth First search, however I have found that it occasionally goes back over itself (crosses its own path) and am not sure if this is the best way to go about it.
Options considered: I have looked at using A*, but am struggling to figure out a good way to do it without a predetermined goal and the conditions above. I have also considered adding a heuristic to favour blocks that are not on the outside of the grid - but am not sure either of these will solve the issue at hand.
Any help is appreciated and I can add more detail or code if necessary:
public List<GridNode> RandomizedDepthFirst(int distance, GridNode startNode)
{
Stack<GridNode> frontier = new Stack<GridNode>();
frontier.Push(startNode);
List<GridNode> visited = new List<GridNode>();
visited.Add(startNode);
while (frontier.Count > 0 && visited.Count < distance)
{
GridNode current = frontier.Pop();
if (current.nodeState != GridNode.NodeState.VISITED)
{
current.nodeState = GridNode.NodeState.VISITED;
GridNode[] vals = current.FindNeighbours().ToArray();
List<GridNode> neighbours = new List<GridNode>();
foreach (GridNode g in vals.OrderBy(x => XMLReader.NextInt(0,0)))
{
neighbours.Add(g);
}
foreach (GridNode g in neighbours)
{
frontier.Push(g);
}
if (!visited.Contains(current))
{
visited.Add(current);
}
}
}
return visited;
}
An easy way to account for back tracking is using a recursive dfs search.
Consider the following graph:
And a java implementation of a dfs search, removing nodes from the path when backtracking (note the comments. Run it online here) :
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
public class Graph {
//all graph nodes
private Node[] nodes;
public Graph(int numberOfNodes) {
nodes = new Node[numberOfNodes];
//construct nodes
for (int i = 0; i < numberOfNodes; i++) {
nodes[i] = new Node(i);
}
}
// add edge from a to b
public Graph addEdge(int from, int to) {
nodes[from].addNeighbor(nodes[to]);
//unless unidirectional: //if a is connected to b
//than b should be connected to a
nodes[to].addNeighbor(nodes[from]);
return this; //makes it convenient to add multiple edges
}
//returns a list of path size of pathLength.
//if path not found : returns an empty list
public List<Node> dfs(int pathLength, int startNode) {
List<Node> path = new ArrayList<>(); //a list to hold all nodes in path
Stack<Node> frontier = new Stack<>();
frontier.push(nodes[startNode]);
dfs(pathLength, frontier, path);
return path;
}
private boolean dfs(int pathLength, Stack<Node> frontier, List<Node> path) {
if(frontier.size() < 1) {
return false; //stack is empty, no path found
}
Node current = frontier.pop();
current.setVisited(true);
path.add(current);
if(path.size() == pathLength) {
return true; //path size of pathLength found
}
System.out.println("testing node "+ current); //for testing
Collections.shuffle(current.getNeighbors()); //shuffle list of neighbours
for(Node node : current.getNeighbors()) {
if(! node.isVisited()) {
frontier.push(node);
if(dfs(pathLength, frontier, path)) { //if solution found
return true; //return true. continue otherwise
}
}
}
//if all neighbours tested and no solution found, current node
//is not part of the path
path.remove(current); // remove it
current.setVisited(false); //this accounts for loops: you may get to this node
//from another edge
return false;
}
public static void main(String[] args){
Graph graph = new Graph(9); //make graph
graph.addEdge(0, 4) //add edges
.addEdge(0, 1)
.addEdge(1, 2)
.addEdge(1, 4)
.addEdge(4, 3)
.addEdge(2, 3)
.addEdge(2, 5)
.addEdge(3, 5)
.addEdge(1, 6)
.addEdge(6, 7)
.addEdge(7, 8);
//print path with length of 6, starting with node 1
System.out.println( graph.dfs(6,1));
}
}
class Node {
private int id;
private boolean isVisited;
private List<Node>neighbors;
Node(int id){
this.id = id;
isVisited = false;
neighbors = new ArrayList<>();
}
List<Node> getNeighbors(){
return neighbors;
}
void addNeighbor(Node node) {
neighbors.add(node);
}
boolean isVisited() {
return isVisited;
}
void setVisited(boolean isVisited) {
this.isVisited = isVisited;
}
#Override
public String toString() {return String.valueOf(id);} //convenience
}
Output:
testing node 1
testing node 6
testing node 7
testing node 8
testing node 2
testing node 5
testing node 3
testing node 4
[1, 2, 5, 3, 4, 0]
Note that nodes 6,7,8 which are dead-end, are tested, but not included in the final path.

Strongly component

I am trying to write an algorithm that is given a graph G and 2 nodes 'x' and 'y'as input, which returns whether there is a cyclic path from 'x' to 'y'
Is it a good idea to find the strongly connected components first and then check if x and y belong to same strongly connected component. If they belong to different connected component say x belongs to C1 and y belongs to C2, then if there exists a path from C1 to C2, then we can say that there is a cyclic path from x to y.
Your idea with strongly connected components should work. Here is a graph and some code for you to experiment:
First, a digraph:
And it's adjacency lists representation:
13 vertices, 22 edges
0: 5 1
1:
2: 0 3
3: 5 2
4: 3 2
5: 4
6: 9 4 8 0
7: 6 9
8: 6
9: 11 10
10: 12
11: 4 12
12: 9
And it's strongly connected components:
7
6 8
9 10 11 12
0 2 3 4 5
1
Now, after with implementation for digraph and Kosaraju-Sharir
class StronglyConnectedComponents
{
private bool[] visited;
private int[] componentIds;
public int ComponentCount { get; private set; }
public StronglyConnectedComponents(DirectedGraph graph)
{
visited = new bool[graph.VertexCount];
componentIds = new int[graph.VertexCount];
var order = new GraphTraversal(graph).ReverseOrder();
var reversedGraph = graph.Reverse();
foreach (var vertex in order)
{
if (!visited[vertex])
{
DepthFirstSearch(reversedGraph, vertex);
ComponentCount++;
}
}
}
public int VertexComponentId(int vertex)
{
return componentIds[vertex];
}
public bool AreStronglyConnected(int source, int target)
{
return componentIds[source] == componentIds[target];
}
private void DepthFirstSearch(DirectedGraph graph, int vertex)
{
visited[vertex] = true;
componentIds[vertex] = ComponentCount;
foreach (var adjacent in graph.AdjacentTo(vertex))
{
if (!visited[adjacent])
{
DepthFirstSearch(graph, adjacent);
}
}
}
}
class GraphTraversal
{
private Stack<int> reversePostOrder;
private bool[] visited;
public GraphTraversal(DirectedGraph graph)
{
visited = new bool[graph.VertexCount];
reversePostOrder = new Stack<int>();
for (var vertex = 0; vertex < graph.VertexCount; vertex++)
{
if (!visited[vertex])
{
DepthFirstSearch(graph, vertex);
}
}
}
public IEnumerable<int> ReverseOrder()
{
return reversePostOrder;
}
private void DepthFirstSearch(DirectedGraph graph, int vertex)
{
visited[vertex] = true;
foreach (var adjacent in graph.AdjacentTo(vertex))
{
if (!visited[adjacent])
{
DepthFirstSearch(graph, adjacent);
}
}
reversePostOrder.Push(vertex);
}
}
class DirectedGraph
{
public int VertexCount { get; set; }
public int EdgeCount { get; set; } = 0;
private List<int>[] adjacencyLists;
public DirectedGraph(int vertexCount)
{
VertexCount = vertexCount;
InitializeAdjacencyLists(vertexCount);
}
public void AddEdge(int from, int to)
{
adjacencyLists[from].Add(to);
EdgeCount++;
}
public IEnumerable<int> AdjacentTo(int vertex)
{
return adjacencyLists[vertex];
}
public DirectedGraph Reverse()
{
var reversedGraph = new DirectedGraph(this.VertexCount);
for (var vertex = 0; vertex < this.VertexCount; vertex++)
{
foreach (var adjacent in this.AdjacentTo(vertex))
{
reversedGraph.AddEdge(adjacent, vertex);
}
}
return reversedGraph;
}
public override string ToString()
{
String graghString = VertexCount + " vertices, " + EdgeCount + " edges \n";
for (int vertex = 0; vertex < VertexCount; vertex++)
{
graghString += vertex + ": ";
foreach (var adjacnet in this.AdjacentTo(vertex))
{
graghString += adjacnet + " ";
}
graghString += "\n";
}
return graghString;
}
private void InitializeAdjacencyLists(int vertexCount)
{
adjacencyLists = new List<int>[vertexCount];
for (var vertex = 0; vertex < vertexCount; vertex++)
{
adjacencyLists[vertex] = new List<int>();
}
}
}
Queries like scc.AreStronglyConnected(2, 5) will tell if directed cycle between vertices exists. Runnable code is here.
I am assuming you want to count paths having 'x' or 'y' multiple times as well.
If 'x' and 'y' belong to same strongly connected component, there exists a path containing a cycle. (trivial, by definition of strongly connected component)
However, if they belong to different strongly connected components, 'y' should be reachable from 'x' and at least one component having a node on the path must have size more than one. (Take any cycle in that component and continue on the path)
Your solution will fail in case of a linear graph. There is no cycle, yet you can reach from 'x' to 'y' which belong to different strongly connected components.

Is it possible to design a tree where nodes have infinitely many children?

How can design a tree with lots (infinite number) of branches ?
Which data structure we should use to store child nodes ?
You can't actually store infinitely many children, since that won't fit into memory. However, you can store unboundedly many children - that is, you can make trees where each node can have any number of children with no fixed upper bound.
There are a few standard ways to do this. You could have each tree node store a list of all of its children (perhaps as a dynamic array or a linked list), which is often done with tries. For example, in C++, you might have something like this:
struct Node {
/* ... Data for the node goes here ... */
std::vector<Node*> children;
};
Alternatively, you could use the left-child/right-sibling representation, which represents a multiway tree as a binary tree. This is often used in priority queues like binomial heaps. For example:
struct Node {
/* ... data for the node ... */
Node* firstChild;
Node* nextSibling;
};
Hope this helps!
Yes! You can create a structure where children are materialized on demand (i.e. "lazy children"). In this case, the number of children can easily be functionally infinite.
Haskell is great for creating "functionally infinite" data structures, but since I don't know a whit of Haskell, here's a Python example instead:
class InfiniteTreeNode:
''' abstract base class for a tree node that has effectively infinite children '''
def __init__(self, data):
self.data = data
def getChild(self, n):
raise NotImplementedError
class PrimeSumNode(InfiniteTreeNode):
def getChild(self, n):
prime = getNthPrime(n) # hypothetical function to get the nth prime number
return PrimeSumNode(self.data + prime)
prime_root = PrimeSumNode(0)
print prime_root.getChild(3).getChild(4).data # would print 18: the 4th prime is 7 and the 5th prime is 11
Now, if you were to do a search of PrimeSumNode down to a depth of 2, you could find all the numbers that are sums of two primes (and if you can prove that this contains all even integers, you can win a big mathematical prize!).
Something like this
Node {
public String name;
Node n[];
}
Add nodes like so
public Node[] add_subnode(Node n[]) {
for (int i=0; i<n.length; i++) {
n[i] = new Node();
p("\n Enter name: ");
n[i].name = sc.next();
p("\n How many children for "+n[i].name+"?");
int children = sc.nextInt();
if (children > 0) {
Node x[] = new Node[children];
n[i].n = add_subnode(x);
}
}
return n;
}
Full working code:
class People {
private Scanner sc;
public People(Scanner sc) {
this.sc = sc;
}
public void main_thing() {
Node head = new Node();
head.name = "Head";
p("\n How many nodes do you want to add to Head: ");
int nodes = sc.nextInt();
head.n = new Node[nodes];
Node[] n = add_subnode(head.n);
print_nodes(head.n);
}
public Node[] add_subnode(Node n[]) {
for (int i=0; i<n.length; i++) {
n[i] = new Node();
p("\n Enter name: ");
n[i].name = sc.next();
p("\n How many children for "+n[i].name+"?");
int children = sc.nextInt();
if (children > 0) {
Node x[] = new Node[children];
n[i].n = add_subnode(x);
}
}
return n;
}
public void print_nodes(Node n[]) {
if (n!=null && n.length > 0) {
for (int i=0; i<n.length; i++) {
p("\n "+n[i].name);
print_nodes(n[i].n);
}
}
}
public static void p(String msg) {
System.out.print(msg);
}
}
class Node {
public String name;
Node n[];
}
I recommend you to use a Node class with a left child Node and right child Node and a parent Node.
public class Node
{
Node<T> parent;
Node<T> leftChild;
Node<T> rightChild;
T value;
Node(T val)
{
value = val;
leftChild = new Node<T>();
leftChild.parent = this;
rightChild = new Node<T>();
rightChild.parent = this;
}
You can set grand father and uncle and sibling like this.
Node<T> grandParent()
{
if(this.parent.parent != null)
{
return this.parent.parent;
}
else
return null;
}
Node<T> uncle()
{
if(this.grandParent() != null)
{
if(this.parent == this.grandParent().rightChild)
{
return this.grandParent().leftChild;
}
else
{
return this.grandParent().rightChild;
}
}
else
return null;
}
Node<T> sibling()
{
if(this.parent != null)
{
if(this == this.parent.rightChild)
{
return this.parent.leftChild;
}
else
{
return this.parent.rightChild;
}
}
else
return null;
}
And is impossible to have infinite child, at least you have infinite memory.
good luck !
Hope this will help you.

Resources