I\'m concerned that this might be working on an NP-Complete problem. I\'m hoping someone can give me an answer as to whether it is or not. And I\'m looking for more of an an
Assuming that you have an adjacency matrix:
bool[,] adj = new bool[n, n];
Where bool[i,j] = true if there is an open path between i and j and bool[i,i] = false.
public bool pathExists(int[,] adj, int start, int end)
{
List<int> visited = new List<int>();
List<int> inprocess = new List<int>();
inprocess.Add(start);
while(inprocess.Count > 0)
{
int cur = inprocess[0];
inprocess.RemoveAt(0);
if(cur == end)
return true;
if(visited.Contains(cur))
continue;
visited.Add(cur);
for(int i = 0; i < adj.Length; i++)
if(adj[cur, i] && !visited.Contains(i) && !inprocess.Contains(i))
inprocess.Add(i);
}
return false;
}
Here is a recursive version of the algorithm above (written in Ruby):
def connected? from, to, edges
return true if from == to
return true if edges.include?([from, to])
return true if edges.include?([to, from])
adjacent = edges.find_all { |e| e.include? from }
.flatten
.reject { |e| e == from }
return adjacent.map do |a|
connected? a, to, edges.reject { |e| e.include? from }
end.any?
end
Your description seems to indicate that you are just interested in whether two nodes are connected, not finding the shortest path.
Finding if two nodes are connected is relatively easy:
Create two sets of nodes: toDoSet and doneSet
Add the source node to the toDoSet
while (toDoSet is not empty) {
Remove the first element from toDoSet
Add it to doneSet
foreach (node reachable from the removed node) {
if (the node equals the destination node) {
return success
}
if (the node is not in doneSet) {
add it to toDoSet
}
}
}
return failure.
If you use a hash table or something similar for toDoSet and doneSet, I believe this is a linear algorithm.
Note that this algorithm is basically the mark portion of mark-and-sweep garbage collection.
I see you have got your answer that it's definitely not NP-Complete and this is a very old question as well.
However, I'll just propose another approach to look at the problem. You could use disjoint sets for this. In most cases, for the given scenario, the approach will result in better time than doing a graph traversal (That includes constant time for a large chunk of tests). However, building the graph might take good amount of time, if union by rank or path compression is used.
You can read about the Data Structure here.
Any graph shortest path algorithm will be overkill if all you need is to find if a node is connected to another. A good Java library that accomplishes that is JGraphT. It's usage is quite simple, here's an example of an Integer graph:
public void loadGraph() {
// first we create a new undirected graph of Integers
UndirectedGraph<Integer, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class);
// then we add some nodes
graph.addVertex(1);
graph.addVertex(2);
graph.addVertex(3);
graph.addVertex(4);
graph.addVertex(5);
graph.addVertex(6);
graph.addVertex(7);
graph.addVertex(8);
graph.addVertex(9);
graph.addVertex(10);
graph.addVertex(11);
graph.addVertex(12);
graph.addVertex(13);
graph.addVertex(14);
graph.addVertex(15);
graph.addVertex(16);
// then we connect the nodes
graph.addEdge(1, 2);
graph.addEdge(2, 3);
graph.addEdge(3, 4);
graph.addEdge(3, 5);
graph.addEdge(5, 6);
graph.addEdge(6, 7);
graph.addEdge(7, 8);
graph.addEdge(8, 9);
graph.addEdge(9, 10);
graph.addEdge(10, 11);
graph.addEdge(11, 12);
graph.addEdge(13, 14);
graph.addEdge(14, 15);
graph.addEdge(15, 16);
// finally we use ConnectivityInspector to check nodes connectivity
ConnectivityInspector<Integer, DefaultEdge> inspector = new ConnectivityInspector<>(graph);
debug(inspector, 1, 2);
debug(inspector, 1, 4);
debug(inspector, 1, 3);
debug(inspector, 1, 12);
debug(inspector, 16, 5);
}
private void debug(ConnectivityInspector<Integer, DefaultEdge> inspector, Integer n1, Integer n2) {
System.out.println(String.format("are [%s] and [%s] connected? [%s]", n1, n2, inspector.pathExists(n1, n2)));
}
This lib also offers all the shortest paths algorithms as well.
See http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm , your one stop shop for all graph related problems. I believe your problem is in fact solvable in quadratic time.
The problem of finding the shortest path isn't NP-complete. It's called the Shortest Path Problem (originally enough) and there are algorithms for solving many different variations of it.
The problem of determining if two nodes are connected isn't NP-complete either. You can use a depth first search starting at either node to determine if it is connected to the other node.