Finding all paths between two nodes on a DAG - algorithm

I have a DAG that has the following adjacency list
L | G, B, P
G | P, I
B | I
P | I
I | R
R | \
I want to find all paths from L to R. I know that I have to do some kind of DFS, and this is what I have so far. (Excuse the Javascript)
function dfs(G, start_vertex) {
const fringe = []
const visited = new Set()
const output = []
fringe.push(start_vertex)
while (fringe.length != 0) {
const vertex = fringe.pop()
if (!visited.has(vertex)) {
output.push(vertex)
for (neighbor in G[vertex].neighbors) {
fringe.push(neighbor)
}
visited.add(vertex)
}
}
return output
}
The output of dfs(G, "L") is [ 'L', 'P', 'I', 'R', 'B', 'G' ] which is indeed a depth first traversal of this graph, but not the result I'm looking for. After doing some searching, I realize there may be a recursive solution, but there were some comments about this problem being "NP-hard" and something about "exponential paths" which I don't understand.

The problem is indeed np-hard because the number of possible paths between two nodes is exponential to the number of nodes. so no way around having a worst-case exponential runtime.

All paths with start head to vertex vertex can be split into paths with heads head||v where v is adjacent to final vertex of head, unless final vertex of head is already vertex: (pseudo-javascript, can have syntax problems)
function print_all_rec(G, head, vertex){
if(head[head.length-1] == vertex){
print(head); //we're here
return;
}
for(v in head[head.length-1].neighbors){
var newHead = head; newHead.append(v);
print_all_rec(G, newHead, vertex);
}
}
function print_all_routes(G, from, to){
var start = [];
start.append(from);
print_all_rec(G, start, to);
}

Related

Code for finding redundant edges in a undirected tree partially working

I am solving the question 684. Redundant Connection from from Leetcode with partial success (I am failing one of the testcases). The question is asked as following:
In this problem, a tree is an undirected graph that is connected and
has no cycles.
You are given a graph that started as a tree with n nodes labeled from
1 to n, with one additional edge added. The added edge has two
different vertices chosen from 1 to n, and was not an edge that
already existed. The graph is represented as an array edges of length
n where edges[i] = [ai, bi] indicates that there is an edge between
nodes ai and bi in the graph.
Return an edge that can be removed so that the resulting graph is a
tree of n nodes. If there are multiple answers, return the answer that
occurs last in the input.
I solved this using BFS which gives a time complexity of O(n^2), however I read that using union-find will give a time complexity of O(n). My try with using union-find+path compression is only partially working, and I am stuck figuring out why.
For these following data, my code is working correctly (Meaning my code returns correct edge):
However, for this testcase below, my code don't succeed in finding the correct edge (My union-find runs through all the edges and return false, meaning there was no redundant edges):
Input data: [[7,8],[2,6],[2,8],[1,4],[9,10],[1,7],[3,9],[6,9],[3,5],[3,10]]
From logs i can see that my union-find constructs the graph as following (with no detected redundant edges):
Here is my code:
class Solution {
fun findRedundantConnection(edges: Array<IntArray>): IntArray {
val parents = IntArray(edges.size + 1) // 1 to N, we dont use 0
for(i in 1..parents.size - 1)
parents[i] = i //each node is its own parent, since this is a undirected graph
val rank = IntArray(edges.size + 1){ 1 } //all nodes have rank 1 since they are their own parent
val res = IntArray(2)
for(edge in edges){
val (node1, node2) = edge
if(union(node1,node2, parents, rank, res) == false)
return intArrayOf(node1, node2)
}
return res
}
private fun find(
node: Int,
parents: IntArray
): Int{
var parent = parents[node]
while(parents[node] != parent){
parents[parent] = parents[parents[parent]] //path compression
parent = parents[parent]
}
return parent
}
//modified union which return false on redundant connection
private fun union(
node1: Int,
node2: Int,
parents: IntArray,
rank: IntArray,
res: IntArray
): Boolean{
val parent1 = find(node1, parents)
val parent2 = find(node2, parents)
if(parent1 == parent2){ //redundant connection
res[0] = node1
res[1] = node2
return false
}
if(rank[parent1] > rank[parent2]){
parents[parent2] = parent1
rank[parent1] += rank[parent2]
}else{ // rank[parent1] <= rank[parent2]
parents[parent1] = parent2
rank[parent2] += rank[parent1]
}
return true
}
}
Any suggestions on what the problem might be? I have not been able to figure it out.
var parent = parents[node]
while(parents[node] != parent){
You're never going to get into the while loop.

How to calculate all possible cycles (all nodes must be visited once) on a graph? Hamilton circle

I am trying to write a program which
outputs all possible cycles starting and ending with node 1 and visiting all other nodes exactly once.
Given is a complete undirected unweighted graph with N nodes.
For example:
n = 4 then
1-2-3-4, 1-2-4-3, 1-3-2-4, 1-3-4-2, 1-4-3-2, 1-4-2-3
My approach would be to use Hamilton-circle method to find out a possible combination and then iterate until all combinations are calculated.
I assume the complexity is (n-1)!
class Permutation
main {
string list1 = "1"
string list2 = "2,3,4"
l2 = list2.length()
init Permutation
permutaion.permute (list2, 0, n-1)!
print list1 + list2
}
permute(list2, start, end) {
if (start==end)
print list2
else
for (i=start, i<=end, i++)
list2 = swap(list2, start, i)
permute(list2, start+1, end)
list2 = swap(list2, start, i)
}
Thank you for your time and help!

printing the permutation using bfs or dfs

I am trying to print all the permutations of a string using recursion as below. But I was wondering if we can use bfs or dfs also to do this, am I thinking right?
If yes, then can you please give me an idea?
My idea is: if string = "abcd"
start node: 'a'
end node: 'd'
intermediate nodes: 'b' and 'c'
We can then change the start nodes to 'b','c' and 'd'.
I am having difficulty in visualizing it to put it in a algorithm.
#include <stdio.h>
void swap(char *s, int i, int j)
{
char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
void foo(char *s, int j, int len)
{
int i;
if (j == len-1) {
printf("%s\n", s);
return;
}
for (i=j;i<len;i++) {
swap(s, i, j);
foo(s, j+1, len);
swap(s, i, j);
}
}
int main()
{
char s[] = "abc";
foo(s, 0, strlen(s));
}
Based on the logic given by Serge Rogatch, below problem can be solved:
def swap_two(s, i, j):
return s[:i] + s[j] + s[i+1:j] + s[i] + s[j+1:]
def swaps(s):
for i in range(1, len(s)):
yield swap_two(s, 0, i)
def print_permutations(input, q):
seen_list = []
q.enqueue(input)
while not q.isempty():
data = q.dequeue()
for i in swaps(data):
if i not in seen_list:
q.enqueue(i)
seen_list.append(i)
return seen_list
q = queue(512)
seen_list = print_permutations("abcd", q)
print(sorted(seen_list), len(seen_list))
queue implementation is here
Your algorithm seems to already implement backtracking, which is one of the correct things to do for permuting. There is also non-recursive algorithm based on tail inversion (can't find the link, I think I don't remember its name precisely) or QuickPerm algorithm: http://www.quickperm.org/quickperm.html
DFS and BFS visit every vertex exactly once. So if you really want to use them, then as vertices you should view permutations (whole strings like "abcd", "abdc", etc.) rather than separate characters like 'a', 'b', etc. Starting with some initial vertex like "abcd" you should try to swap each pair of characters and see if that vertex has been already visited. You can store the set of visited vertices in an unordered_set. So e.g. in "abcd" if you swap 'b' and 'c' you get "acbd" etc. This algorithm should produce each permutation because for Heap's algorithm it suffices to swap just one pair of vertices in each step: https://en.wikipedia.org/wiki/Heap%27s_algorithm
If you strictly want to emulate a graph traversal algorithm...Here's an intuitive(probably not the most graceful) approach:
Think of string as a graph, where each character is connected to every other character
Instead of trying to find a "path" from source to destination, frame the problem as follows: "find all paths of a specific length - from every source"
So start from the first character, use it as the "source"; then find all paths with length = length of the entire String... Then use the next character as the source...
Here's an implementation in python:
def permutations(s):
g = _str_to_graph(s) # {'a': ['b', 'c'], 'b': ['c', 'a'], 'c': ['a', 'b'] }
branch = []
visited = set()
for i in s: # use every character as a source
dfs_all_paths_of_certain_length(i, len(s), branch, visited, g)
def _str_to_graph(s):
from collections import defaultdict
g = defaultdict(list)
for i in range(len(s)):
for j in range(len(s)):
if i != j:
g[s[i]].append(s[j])
return g
def dfs_all_paths_of_certain_length(u, ll, branch, visited, g):
visited.add(u)
branch.append(u)
if len(branch) == ll: # if length of branch equals length of string, print the branch
print("".join(branch))
else:
for n in g[u]:
if n not in visited:
dfs_all_paths_of_certain_length(n, ll, branch, visited, g)
# backtrack
visited.remove(u)
branch.remove(u)
You can read this article:
http://en.cppreference.com/w/cpp/algorithm/next_permutation
AlTHOUGH this is C++ implementation, but you can easily transform it to a C version
By the way, your method can be called a dfs!

Algorithm to find and print simple cycle in complexity of O(n) on undirected graph

Given graph G(V,E), un-directed graph.
|E| = m, |V| = n
The graph's data structure is Adjacency list
How to find and print simple cycle (or print that there is no such cycle) in complexity of O(n)?
(If there is cycle the output should be the list of vertex that are part of the cycle.)
I know how to find cycle on complexity of O(n), there is also gudies on the internet.
My problem is how to print it.
This is what I tried to do:
DFS-CheckCycle ( Graph G)
{
p[] <- null //parent array
foreach v in V
Color[u] <- white
foreach v in V
{
if (Color[u] = white)
Visit(u)
}
}
Visit(Vertex u)
{
bool Cycle <- false;
Color[u] <- gray
foreach v in Adj[u]
{
p[v] <- u
if (Color[v] = white)
Visit(v);
else if (Color[v] = gray)
{
Cycle <- true;
break;
}
}
if(!Cycle)
print "No Cycle"
else
PrintCycle(v,u)
}
PrintCycle(Vertex v, Vertex u)
{
if(v = u)
print v;
else
{
print v;
PrintCycle(p[v], u);
}
}
remember that it needs to be O(n).
My PrintCycle function doesn't print all the vertexes.
I need some help how to print the vertexes of the cycle I found.
I noticed two things which does not seem correct in your algorithm. Firstly, when you use your DFS walk, you should maintain the following invariant:
Unvisited vertices should be painted white; (you did that)
Visited vertices, for which Visit() hasn't ended yet, should be painted gray;
Visited vertices, for which Visit() has returned should be painted black(or color, other than gray or white).
The other thing I noticed, you don't assign parents for nodes correctly. In your Visit() method parents are assigned even if the vertex we want to visit on the next step is gray, i.e. already has a parent in DFS-tree.
So I would change your code accordingly:
DFS-CheckCycle ( Graph G)
{
p[] <- null //parent array
foreach v in V
Color[v] <- white
foreach u in V
{
if (Color[u] = white) {
p[u] <- -1; // meaning it is a root of a DFS-tree of the DFS forest
Visit(u)
}
}
}
Visit(Vertex u)
{
bool Cycle <- false;
Color[u] <- gray
foreach v in Adj[u]
{
if (Color[v] = white) {
p[v] <- u
Visit(v);
}
else if (Color[v] = gray)
{
Cycle <- true;
break;
}
}
Color[u] <- black; // once DFS for this vertex ends, assign its color to black
if(!Cycle)
print "No Cycle"
else
PrintCycle(v,u)
}
PrintCycle(Vertex v, Vertex u)
{
if(v = u)
print v;
else
{
print v;
PrintCycle(p[v], u);
}
}
EDIT: It might be a good idea to turn your PrintCycle method into non-recursive one:
PrintCycle(Vertex v, Vertex u)
{
do {
print u;
u = p[u];
} while (u != v);
}
In the recursive search, you can add a parameter that is a chain of ancestors all the way to the search root. The cycle will consist of the current node and those in the chain ending at the gray node found to discover the cycle.
By chain I mean a lisp-style list: a pair consisting of a node and another pair, the final pair being null.
A more straightforward way is to search with an explicit stack rather than recursion. The Nodes on the stack are all gray. When you find a gray node indicating cycle, the cycle can be printed by working backward through the stack.

4x4 2D character matrix permutations

I have a 4x4 2D array of characters like this:
A B C D
U A L E
T S U G
N E Y I
Now, I would need to find all the permutations of 3 characters, 4 characters, etc till 10.
So, some words that one could "find" out of this are TEN, BALD, BLUE, GUYS.
I did search SO for this and Googled, but to no concrete help. Can you push me in the right direction in which algorithm I should learn (A* maybe?). Please be gentle as I'm no algorithms guy (aren't we all (well, at least a majority :)), but am willing to learn just don't know where exactly to start.
Ahhh, that's the game Boggle isn't it... You don't want permutations, you want a graph and you want to find words in the graph.
Well, I would start by arranging the characters as graph nodes, and join them to their immediate and diagonal neighbours.
Now you just want to search the graph. For each of the 16 starting nodes, you're going to do a recursion. As you move to a new node, you must flag it as being used so that you can't move to it again. When you leave a node (having completely searched it) you unflag it.
I hope you see where this is going...
For each node, you will visit each of its neighbours and add that character to a string. If you have built your dictionary with this search in mind, you will immediately be able to see whether the characters you have so far are the beginning of a word. This narrows the search nicely.
The kind of dictionary I'm talking about is where you have a tree whose nodes have one child for each letter of the alphabet. The beauty of these is that you only need to store which tree node you're currently up to in the search. If you decide you've found a word, you just backtrack via the parent nodes to work out which word it is.
Using this tree style along with a depth-first graph search, you can search ALL possible word lengths at the same time. That's about the most efficient way I can think of.
Let me just write a pseudocodish function for your graph search:
function FindWords( graphNode, dictNode, wordsList )
# can't use a letter twice
if graphNode.used then return
# don't continue if the letter not part of any word
if not dictNode.hasChild(graphNode.letter) then return
nextDictNode = dictNode.getChild(graphNode.letter)
# if this dictionary node is flagged as a word, add it to our list
nextDictNode.isWord()
wordsList.addWord( nextDictNode .getWord() )
end
# Now do a recursion on all our neighbours
graphNode.used = true
foreach nextGraphNode in graphNode.neighbours do
FindWords( nextGraphNode, nextDictNode, wordsList )
end
graphNode.used = false
end
And of course, to kick the whole thing off:
foreach graphNode in graph do
FindWords( graphNode, dictionary, wordsList )
end
All that remains is to build the graph and the dictionary. And I just remembered what that dictionary data structure is called! It's a Trie. If you need more space-efficient storage, you can compress into a Radix Tree or similar, but by far the easiest (and fastest) is to just use a straight Trie.
As you not define preferred language I implemented on C#:
private static readonly int[] dx = new int[] { 1, 1, 1, 0, 0, -1, -1, -1 };
private static readonly int[] dy = new int[] { -1, 0, 1, 1, -1, -1, 0, 1 };
private static List<string> words;
private static List<string> GetAllWords(char[,] matrix ,int d)
{
words = new List<string>();
bool[,] visited = new bool[4, 4];
char[] result = new char[d];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
Go(matrix, result, visited, d, i, j);
return words;
}
private static void Go(char[,] matrix, char[] result, bool[,] visited, int d, int x, int y)
{
if (x < 0 || x >= 4 || y < 0 || y >= 4 || visited[x, y])
return;
if (d == 0)
{
words.Add(new String(result));
return;
}
visited[x, y] = true;
result[d - 1] = matrix[x, y];
for (int i = 0; i < 8; i++)
{
Go(matrix, result, visited, d - 1, x + dx[i], y + dy[i]);
}
visited[x, y] = false;
}
Code to get results:
char[,] matrix = new char[,] { { 'A', 'B', 'C', 'D' }, { 'U', 'A', 'L', 'E' }, { 'T', 'S', 'U', 'G' }, { 'N', 'E', 'Y', 'I' } };
List<string> list = GetAllWords(matrix, 3);
Change parameter 3 to required text length.
It seems you just use the 4x4 matrix as an array of length 16. If it is the case, you can try the recursive approach to generate permutations up to length k as follows:
findPermutations(chars, i, highLim, downLim, candidate):
if (i > downLim):
print candidate
if (i == highLim): //stop clause
return
for j in range(i,length(chars)):
curr <- chars[i]
candidate.append(curr)
swap(chars,i,j) // make it unavailable for repicking
findPermutations(chars,i+1,highLim,downLim,candidate)
//clean up environment after recursive call:
candidate.removeLast()
swap(chars ,i, j)
The idea is to print each "candidate" that has more chars then downLim (3 in your case), and terminate when you reach the upper limit (highLim) - 10 in your case.
At each time, you "guess" which character is the next to put - and you append it to the candidate, and recursively invoke to find the next candidate.
Repeat the process for all possible guesses.
Note that there are choose(10,16)*10! + choose(9,16)*9! + ... + choose(3,16)*3! different such permutations, so it might be time consuming...
If you want meaningful words, you are going to need some kind of dictionary (or to statistically extract one from some context) in order to match the candidates with the "real words".

Resources