Java 从源节点到目标节点的所有可能路径的成本/距离

Java 从源节点到目标节点的所有可能路径的成本/距离,java,path-finding,Java,Path Finding,在我的应用程序中,室内导航…在特定情况下。。。。我必须找到从特定来源到用户提供的目的地的所有可能路径。。。 Algo工作正常,给出了所有可能的路径。。。。但是如何计算这些路径的距离呢。。??? 这是工作算法 class GraphFindAllPaths<T> implements Iterable<T> { /* A map from nodes in the graph to sets of outgoing edges. Each * set of edges

在我的应用程序中,室内导航…在特定情况下。。。。我必须找到从特定来源到用户提供的目的地的所有可能路径。。。 Algo工作正常,给出了所有可能的路径。。。。但是如何计算这些路径的距离呢。。??? 这是工作算法

class GraphFindAllPaths<T> implements Iterable<T> {

/* A map from nodes in the graph to sets of outgoing edges.  Each
 * set of edges is represented by a map from edges to doubles.
 */
public final Map<T, Map<T, Double>> graph = new HashMap<T, Map<T, Double>>();

/**
 *  Adds a new node to the graph. If the node already exists then its a
 *  no-op.
 * 
 * @param node  Adds to a graph. If node is null then this is a no-op.
 * @return      true if node is added, false otherwise.
 */


public boolean addNode(T node) {
    if (node == null) {
        throw new NullPointerException("The input node cannot be null.");
    }
    if (graph.containsKey(node)) return false;

    graph.put(node, new HashMap<T, Double>());
    return true;
}

/**
 * Given the source and destination node it would add an arc from source 
 * to destination node. If an arc already exists then the value would be 
 * updated the new value.
 *  
 * @param source                    the source node.
 * @param destination               the destination node.
 * @param length                    if length if 
 * @throws NullPointerException     if source or destination is null.
 * @throws NoSuchElementException   if either source of destination does not exists. 
 */
public void addEdge (T source, T destination, double length) {
    if (source == null || destination == null) {
        throw new NullPointerException("Source and Destination, both should be non-null.");
    }
    if (!graph.containsKey(source) || !graph.containsKey(destination)) {
        throw new NoSuchElementException("Source and Destination, both should be part of graph");
    }
    /* A node would always be added so no point returning true or false */
    graph.get(source).put(destination, length);



}

/**
 * Removes an edge from the graph.
 * 
 * @param source        If the source node.
 * @param destination   If the destination node.
 * @throws NullPointerException     if either source or destination specified is null
 * @throws NoSuchElementException   if graph does not contain either source or destination
 */
public void removeEdge (T source, T destination) {
    if (source == null || destination == null) {
        throw new NullPointerException("Source and Destination, both should be non-null.");
    }
    if (!graph.containsKey(source) || !graph.containsKey(destination)) {
        throw new NoSuchElementException("Source and Destination, both should be part of graph");
    }
    graph.get(source).remove(destination);
}

/**
 * Given a node, returns the edges going outward that node,
 * as an immutable map.
 * 
 * @param node The node whose edges should be queried.
 * @return An immutable view of the edges leaving that node.
 * @throws NullPointerException   If input node is null.
 * @throws NoSuchElementException If node is not in graph.
 */
public Map<T, Double> edgesFrom(T node) {
    if (node == null) {
        throw new NullPointerException("The node should not be null.");
    }
    Map<T, Double> edges = graph.get(node);
    if (edges == null) {
        throw new NoSuchElementException("Source node does not exist.");
    }
    return Collections.unmodifiableMap(edges);
}

/**
 * Returns the iterator that travels the nodes of a graph.
 * 
 * @return an iterator that travels the nodes of a graph.
 */
@Override public Iterator<T> iterator() {
    //System.out.println(graph.keySet().iterator());
    return graph.keySet().iterator();
}
}

/**
 * Given a connected directed graph, find all paths between any two input points.
 */
public class FindAllPaths<T> {

private final  GraphFindAllPaths<T> graph;

/**
 * Takes in a graph. This graph should not be changed by the client
 */
public FindAllPaths(GraphFindAllPaths<T> graph) {
    if (graph == null) {
        throw new NullPointerException("The input graph cannot be null.");
    }
    this.graph = graph;
}


private void validate (T source, T destination) {

    if (source == null) {
        throw new NullPointerException("The source: " + source + " cannot be  null.");
    }
    if (destination == null) {
        throw new NullPointerException("The destination: " + destination + " cannot be  null.");
    }
    if (source.equals(destination)) {
        throw new IllegalArgumentException("The source and destination: " + source + " cannot be the same.");
    }
}

/**
 * Returns the list of paths, where path itself is a list of nodes.
 * 
 * @param source            the source node
 * @param destination       the destination node
 * @return                  List of all paths
 */
public List<List<T>> getAllPaths(T source, T destination) {
    validate(source, destination);

    List<List<T>> paths = new ArrayList<List<T>>();
    recursive(source, destination, paths, new LinkedHashSet<T>());
    return paths;
}


// so far this dude ignore's cycles.
private void recursive (T current, T destination, List<List<T>> paths, LinkedHashSet<T> path) {
    path.add(current);

    if (current == destination) {
        paths.add(new ArrayList<T>(path));
        path.remove(current);
        return;
    }

    final Set<T> edges  = graph.edgesFrom(current).keySet();

    for (T t : edges) {
        if (!path.contains(t)) {
            //System.out.println(t);
            recursive (t, destination, paths, path);
        }
    }

    path.remove(current);
}    

public static void main(String[] args) {
    GraphFindAllPaths<String> graphFindAllPaths = new GraphFindAllPaths<String>();
    graphFindAllPaths.addNode("A");
    graphFindAllPaths.addNode("B");
    graphFindAllPaths.addNode("C");
    graphFindAllPaths.addNode("D");

    graphFindAllPaths.addEdge("A", "B", 10);
    graphFindAllPaths.addEdge("A", "C", 15);
    graphFindAllPaths.addEdge("B", "A", 10);
    graphFindAllPaths.addEdge("C", "A", 15);
    graphFindAllPaths.addEdge("B", "D", 10);
    graphFindAllPaths.addEdge("C", "D", 20);
    graphFindAllPaths.addEdge("D", "B", 10);
    graphFindAllPaths.addEdge("D", "C", 20);

    graphFindAllPaths.addEdge("B", "C", 5);
    graphFindAllPaths.addEdge("C", "B", 5);



    FindAllPaths<String> findAllPaths = new FindAllPaths<String>(graphFindAllPaths);



    for (List<String> path :findAllPaths.getAllPaths("D", "A"))
    {
        System.out.println(path);
    }


   // assertEquals(paths, findAllPaths.getAllPaths("A", "D"));
}


}

知道每个链接的距离。将沿这些链接的距离相加。完成。

我修改了Maryea提供的代码,以显示每条路径的总成本/距离

package com.mini.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;

class GraphFindAllPaths<T> implements Iterable<T> {

    /* A map from nodes in the graph to sets of outgoing edges.  Each
     * set of edges is represented by a map from edges to doubles.
     */
    public final Map<T, Map<T, Double>> graph = new HashMap<T, Map<T, Double>>();

    /**
     *  Adds a new node to the graph. If the node already exists then its a
     *  no-op.
     * 
     * @param node  Adds to a graph. If node is null then this is a no-op.
     * @return      true if node is added, false otherwise.
     */


    public boolean addNode(T node) {
        if (node == null) {
            throw new NullPointerException("The input node cannot be null.");
        }
        if (graph.containsKey(node)) return false;

        graph.put(node, new HashMap<T, Double>());
        return true;
    }

    /**
     * Given the source and destination node it would add an arc from source 
     * to destination node. If an arc already exists then the value would be 
     * updated the new value.
     *  
     * @param source                    the source node.
     * @param destination               the destination node.
     * @param length                    if length if 
     * @throws NullPointerException     if source or destination is null.
     * @throws NoSuchElementException   if either source of destination does not exists. 
     */
    public void addEdge (T source, T destination, double length) {
        if (source == null || destination == null) {
            throw new NullPointerException("Source and Destination, both should be non-null.");
        }
        if (!graph.containsKey(source) || !graph.containsKey(destination)) {
            throw new NoSuchElementException("Source and Destination, both should be part of graph");
        }
        /* A node would always be added so no point returning true or false */
        graph.get(source).put(destination, length);



    }

    /**
     * Removes an edge from the graph.
     * 
     * @param source        If the source node.
     * @param destination   If the destination node.
     * @throws NullPointerException     if either source or destination specified is null
     * @throws NoSuchElementException   if graph does not contain either source or destination
     */
    public void removeEdge (T source, T destination) {
        if (source == null || destination == null) {
            throw new NullPointerException("Source and Destination, both should be non-null.");
        }
        if (!graph.containsKey(source) || !graph.containsKey(destination)) {
            throw new NoSuchElementException("Source and Destination, both should be part of graph");
        }
        graph.get(source).remove(destination);
    }

    /**
     * Given a node, returns the edges going outward that node,
     * as an immutable map.
     * 
     * @param node The node whose edges should be queried.
     * @return An immutable view of the edges leaving that node.
     * @throws NullPointerException   If input node is null.
     * @throws NoSuchElementException If node is not in graph.
     */
    public Map<T, Double> edgesFrom(T node) {
        if (node == null) {
            throw new NullPointerException("The node should not be null.");
        }
        Map<T, Double> edges = graph.get(node);
        if (edges == null) {
            throw new NoSuchElementException("Source node does not exist.");
        }
        return Collections.unmodifiableMap(edges);
    }


    /**
     * Returns the iterator that travels the nodes of a graph.
     * 
     * @return an iterator that travels the nodes of a graph.
     */
    @Override public Iterator<T> iterator() {
        //System.out.println(graph.keySet().iterator());
        return graph.keySet().iterator();
    }
}

/**
 * Given a connected directed graph, find all paths between any two input points.
 */
public class FindAllPaths<T> {

    private final  GraphFindAllPaths<T> graph;

    /**
     * Takes in a graph. This graph should not be changed by the client
     */
    public FindAllPaths(GraphFindAllPaths<T> graph) {
        if (graph == null) {
            throw new NullPointerException("The input graph cannot be null.");
        }
        this.graph = graph;
    }


    private void validate (T source, T destination) {

        if (source == null) {
            throw new NullPointerException("The source: " + source + " cannot be  null.");
        }
        if (destination == null) {
            throw new NullPointerException("The destination: " + destination + " cannot be  null.");
        }
        if (source.equals(destination)) {
            throw new IllegalArgumentException("The source and destination: " + source + " cannot be the same.");
        }
    }

    /**
     * Returns the list of paths, where path itself is a list of nodes.
     * 
     * @param source            the source node
     * @param destination       the destination node
     * @return                  List of all paths
     */
    public List<List<T>> getAllPaths(T source, T destination) {
        validate(source, destination);
        Map<List<T>,Double> pathWithCost = new HashMap<List<T>,Double>();

        List<List<T>> paths = new ArrayList<List<T>>();
        List<Double> totalCost = new ArrayList<Double>();
        Double cost = new Double(0);
        recursive(source, destination, paths, new LinkedHashSet<T>(),totalCost,cost, new HashMap<T, Double>());
        for(int i=0;i<paths.size();i++){
            pathWithCost.put(paths.get(i), totalCost.get(i));
        }
        return paths;
    }

    // so far this dude ignore's cycles.
    private void recursive (T current, T destination, List<List<T>> paths, LinkedHashSet<T> path, List<Double> totalCost,Double cost, Map<T, Double> allEdges) {
        path.add(current);
        if(allEdges.get(current)!=null){
            cost= cost+allEdges.get(current);
        }
        if (current == destination) {
            cost= cost+allEdges.get(current);
            paths.add(new ArrayList<T>(path));

            cost= cost-allEdges.get(current);
            totalCost.add(cost);
            path.remove(current);
            return;
        }

        allEdges = graph.edgesFrom(current);

        final Set<T> edges  = graph.edgesFrom(current).keySet();

        for (T t : edges) {
            if (!path.contains(t)) {
                //System.out.println(t);
                recursive (t, destination, paths, path,totalCost,cost , allEdges);
            }
        }

        path.remove(current);
    }    


    /**
     * Returns the list of paths, where path itself is a list of nodes.
     * 
     * @param source            the source node
     * @param destination       the destination node
     * @return                  List of all paths
     */
    public  Map<List<T>,Double> getAllPathsWithCost(T source, T destination) {
        validate(source, destination);
        Map<List<T>,Double> pathWithCost = new HashMap<List<T>,Double>();

        List<List<T>> paths = new ArrayList<List<T>>();
        List<Double> totalCost = new ArrayList<Double>();
        Double cost = new Double(0);
        recursiveWithCost(source, destination, paths, new LinkedHashSet<T>(),totalCost,cost, new HashMap<T, Double>());
        for(int i=0;i<paths.size();i++){
            pathWithCost.put(paths.get(i), totalCost.get(i));
        }
        return pathWithCost;
    }

    // so far this dude ignore's cycles.
    private void recursiveWithCost (T current, T destination, List<List<T>> paths, LinkedHashSet<T> path, List<Double> totalCost,Double cost, Map<T, Double> allEdges) {
        path.add(current);
        if(allEdges.get(current)!=null){
            cost= cost+allEdges.get(current);
        }
        if (current == destination) {
            cost= cost+allEdges.get(current);
            paths.add(new ArrayList<T>(path));

            cost= cost-allEdges.get(current);
            totalCost.add(cost);
            path.remove(current);
            return;
        }

        allEdges = graph.edgesFrom(current);

        final Set<T> edges  = graph.edgesFrom(current).keySet();

        for (T t : edges) {
            if (!path.contains(t)) {
                //System.out.println(t);
                recursiveWithCost (t, destination, paths, path,totalCost,cost , allEdges);
            }
        }

        path.remove(current);
    }    


    public static void main(String[] args) {
        GraphFindAllPaths<String> graphFindAllPaths = new GraphFindAllPaths<String>();
        graphFindAllPaths.addNode("A");
        graphFindAllPaths.addNode("B");
        graphFindAllPaths.addNode("C");
        graphFindAllPaths.addNode("D");

        graphFindAllPaths.addEdge("A", "B", 10);
        graphFindAllPaths.addEdge("A", "C", 15);
        graphFindAllPaths.addEdge("B", "A", 10);
        graphFindAllPaths.addEdge("C", "A", 15);
        graphFindAllPaths.addEdge("B", "D", 10);
        graphFindAllPaths.addEdge("C", "D", 20);
        graphFindAllPaths.addEdge("D", "B", 10);
        graphFindAllPaths.addEdge("D", "C", 20);

        graphFindAllPaths.addEdge("B", "C", 5);
        graphFindAllPaths.addEdge("C", "B", 5);



        FindAllPaths<String> findAllPaths = new FindAllPaths<String>(graphFindAllPaths);

        System.out.println("All possible Paths : ");
        for (List<String> path :findAllPaths.getAllPaths("D", "A"))
        {
            System.out.println(path);
        }

        System.out.println("\nAll possible paths with total distance : ");
        Map<List<String>,Double> pathWithCost = findAllPaths.getAllPathsWithCost("D", "A");
        for(Entry<List<String>, Double> s : pathWithCost.entrySet()){
            System.out.println(s);
        }

        // assertEquals(paths, findAllPaths.getAllPaths("A", "D"));
    }


}
package com.mini.test;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.HashMap;
导入java.util.Iterator;
导入java.util.LinkedHashSet;
导入java.util.List;
导入java.util.Map;
导入java.util.Map.Entry;
导入java.util.NoSuchElementException;
导入java.util.Set;
类GraphFindAllPath实现了Iterable{
/*从图中的节点到输出边集的映射。每个
*边集由从边到双边的贴图表示。
*/
公共最终映射图=新HashMap();
/**
*将新节点添加到图形中。如果该节点已存在,则其
*禁止操作。
* 
*@param node添加到图形中。如果node为null,则这是一个no-op。
*@如果添加了节点,则返回true,否则返回false。
*/
公共布尔addNode(T节点){
if(node==null){
抛出新的NullPointerException(“输入节点不能为null”);
}
if(graph.containsKey(node))返回false;
put(node,newhashmap());
返回true;
}
/**
*给定源节点和目标节点,它将从源节点添加一个弧
*到目标节点。如果弧已存在,则该值为
*更新了新值。
*  
*@param source源节点。
*@param destination指定目标节点。
*@param length if length if
*如果源或目标为空,@将引发NullPointerException。
*@如果目标的任何一个源都不存在,则会抛出NoSuchElementException。
*/
公共无效补遗(T源、T目标、双倍长度){
如果(源==null | |目标==null){
抛出新的NullPointerException(“源和目标,两者都应为非null”);
}
如果(!graph.containsKey(源)| |!graph.containsKey(目标)){
抛出新的NoSuchElementException(“源和目标,两者都应该是图形的一部分”);
}
/*始终添加一个节点,这样就不会返回true或false*/
graph.get(源)、put(目的地、长度);
}
/**
*从图形中删除边。
* 
*@param source,如果源节点为。
*@param destination如果是目标节点。
*@如果指定的源或目标为null,则引发NullPointerException
*如果图形既不包含源也不包含目标,@将抛出NoSuchElementException
*/
公共无效删除(T源,T目标){
如果(源==null | |目标==null){
抛出新的NullPointerException(“源和目标,两者都应为非null”);
}
如果(!graph.containsKey(源)| |!graph.containsKey(目标)){
抛出新的NoSuchElementException(“源和目标,两者都应该是图形的一部分”);
}
graph.get(源)、remove(目标);
}
/**
*给定一个节点,返回该节点外的边,
*作为一个不可变的映射。
* 
*@param node应查询其边的节点。
*@返回离开该节点的边的不可变视图。
*如果输入节点为空,@将引发NullPointerException。
*若节点不在图中,@将抛出NoSuchElementException。
*/
公共地图边缘自(T节点){
if(node==null){
抛出新的NullPointerException(“节点不应为null”);
}
映射边=graph.get(节点);
如果(边==null){
抛出新的NoSuchElementException(“源节点不存在”);
}
返回集合。不可修改的映射(边);
}
/**
*返回遍历图的节点的迭代器。
* 
*@返回一个遍历图节点的迭代器。
*/
@重写公共迭代器迭代器(){
//System.out.println(graph.keySet().iterator());
返回graph.keySet().iterator();
}
}
/**
*给定一个连通有向图,找出任意两个输入点之间的所有路径。
*/
公共类FindAllPaths{
私有最终图findallpath图;
/**
*接收图形。客户端不应更改此图形
*/
公共FindAllPath(图FindAllPath图){
if(图==null){
抛出新的NullPointerException(“输入图形不能为null”);
}
this.graph=图形;
}
私有无效验证(T源、T目标){
if(source==null){
抛出新的NullPointerException(“源:“+source+”不能为null”);
}
如果(目标==null){
抛出新的NullPointerException(“目标:“+destination+”不能为null”);
}
if(源等于(目标)){
抛出新的IllegalArgumentException(“源和目标:“+source+”不能相同”);
}
}
/**
*返回路径列表,其中路径本身是节点列表。
* 
*@param source源节点
*@param destination目标节点
*@返回所有路径的列表
*/
公共列表GetAllPath(T源,T目标){
验证(来源、目的地);
Map pathWithCost=new HashMap();
列表路径=新的ArrayList();
List totalCost=new ArrayList();
双倍成本=新的双倍成本(0)
package com.mini.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;

class GraphFindAllPaths<T> implements Iterable<T> {

    /* A map from nodes in the graph to sets of outgoing edges.  Each
     * set of edges is represented by a map from edges to doubles.
     */
    public final Map<T, Map<T, Double>> graph = new HashMap<T, Map<T, Double>>();

    /**
     *  Adds a new node to the graph. If the node already exists then its a
     *  no-op.
     * 
     * @param node  Adds to a graph. If node is null then this is a no-op.
     * @return      true if node is added, false otherwise.
     */


    public boolean addNode(T node) {
        if (node == null) {
            throw new NullPointerException("The input node cannot be null.");
        }
        if (graph.containsKey(node)) return false;

        graph.put(node, new HashMap<T, Double>());
        return true;
    }

    /**
     * Given the source and destination node it would add an arc from source 
     * to destination node. If an arc already exists then the value would be 
     * updated the new value.
     *  
     * @param source                    the source node.
     * @param destination               the destination node.
     * @param length                    if length if 
     * @throws NullPointerException     if source or destination is null.
     * @throws NoSuchElementException   if either source of destination does not exists. 
     */
    public void addEdge (T source, T destination, double length) {
        if (source == null || destination == null) {
            throw new NullPointerException("Source and Destination, both should be non-null.");
        }
        if (!graph.containsKey(source) || !graph.containsKey(destination)) {
            throw new NoSuchElementException("Source and Destination, both should be part of graph");
        }
        /* A node would always be added so no point returning true or false */
        graph.get(source).put(destination, length);



    }

    /**
     * Removes an edge from the graph.
     * 
     * @param source        If the source node.
     * @param destination   If the destination node.
     * @throws NullPointerException     if either source or destination specified is null
     * @throws NoSuchElementException   if graph does not contain either source or destination
     */
    public void removeEdge (T source, T destination) {
        if (source == null || destination == null) {
            throw new NullPointerException("Source and Destination, both should be non-null.");
        }
        if (!graph.containsKey(source) || !graph.containsKey(destination)) {
            throw new NoSuchElementException("Source and Destination, both should be part of graph");
        }
        graph.get(source).remove(destination);
    }

    /**
     * Given a node, returns the edges going outward that node,
     * as an immutable map.
     * 
     * @param node The node whose edges should be queried.
     * @return An immutable view of the edges leaving that node.
     * @throws NullPointerException   If input node is null.
     * @throws NoSuchElementException If node is not in graph.
     */
    public Map<T, Double> edgesFrom(T node) {
        if (node == null) {
            throw new NullPointerException("The node should not be null.");
        }
        Map<T, Double> edges = graph.get(node);
        if (edges == null) {
            throw new NoSuchElementException("Source node does not exist.");
        }
        return Collections.unmodifiableMap(edges);
    }


    /**
     * Returns the iterator that travels the nodes of a graph.
     * 
     * @return an iterator that travels the nodes of a graph.
     */
    @Override public Iterator<T> iterator() {
        //System.out.println(graph.keySet().iterator());
        return graph.keySet().iterator();
    }
}

/**
 * Given a connected directed graph, find all paths between any two input points.
 */
public class FindAllPaths<T> {

    private final  GraphFindAllPaths<T> graph;

    /**
     * Takes in a graph. This graph should not be changed by the client
     */
    public FindAllPaths(GraphFindAllPaths<T> graph) {
        if (graph == null) {
            throw new NullPointerException("The input graph cannot be null.");
        }
        this.graph = graph;
    }


    private void validate (T source, T destination) {

        if (source == null) {
            throw new NullPointerException("The source: " + source + " cannot be  null.");
        }
        if (destination == null) {
            throw new NullPointerException("The destination: " + destination + " cannot be  null.");
        }
        if (source.equals(destination)) {
            throw new IllegalArgumentException("The source and destination: " + source + " cannot be the same.");
        }
    }

    /**
     * Returns the list of paths, where path itself is a list of nodes.
     * 
     * @param source            the source node
     * @param destination       the destination node
     * @return                  List of all paths
     */
    public List<List<T>> getAllPaths(T source, T destination) {
        validate(source, destination);
        Map<List<T>,Double> pathWithCost = new HashMap<List<T>,Double>();

        List<List<T>> paths = new ArrayList<List<T>>();
        List<Double> totalCost = new ArrayList<Double>();
        Double cost = new Double(0);
        recursive(source, destination, paths, new LinkedHashSet<T>(),totalCost,cost, new HashMap<T, Double>());
        for(int i=0;i<paths.size();i++){
            pathWithCost.put(paths.get(i), totalCost.get(i));
        }
        return paths;
    }

    // so far this dude ignore's cycles.
    private void recursive (T current, T destination, List<List<T>> paths, LinkedHashSet<T> path, List<Double> totalCost,Double cost, Map<T, Double> allEdges) {
        path.add(current);
        if(allEdges.get(current)!=null){
            cost= cost+allEdges.get(current);
        }
        if (current == destination) {
            cost= cost+allEdges.get(current);
            paths.add(new ArrayList<T>(path));

            cost= cost-allEdges.get(current);
            totalCost.add(cost);
            path.remove(current);
            return;
        }

        allEdges = graph.edgesFrom(current);

        final Set<T> edges  = graph.edgesFrom(current).keySet();

        for (T t : edges) {
            if (!path.contains(t)) {
                //System.out.println(t);
                recursive (t, destination, paths, path,totalCost,cost , allEdges);
            }
        }

        path.remove(current);
    }    


    /**
     * Returns the list of paths, where path itself is a list of nodes.
     * 
     * @param source            the source node
     * @param destination       the destination node
     * @return                  List of all paths
     */
    public  Map<List<T>,Double> getAllPathsWithCost(T source, T destination) {
        validate(source, destination);
        Map<List<T>,Double> pathWithCost = new HashMap<List<T>,Double>();

        List<List<T>> paths = new ArrayList<List<T>>();
        List<Double> totalCost = new ArrayList<Double>();
        Double cost = new Double(0);
        recursiveWithCost(source, destination, paths, new LinkedHashSet<T>(),totalCost,cost, new HashMap<T, Double>());
        for(int i=0;i<paths.size();i++){
            pathWithCost.put(paths.get(i), totalCost.get(i));
        }
        return pathWithCost;
    }

    // so far this dude ignore's cycles.
    private void recursiveWithCost (T current, T destination, List<List<T>> paths, LinkedHashSet<T> path, List<Double> totalCost,Double cost, Map<T, Double> allEdges) {
        path.add(current);
        if(allEdges.get(current)!=null){
            cost= cost+allEdges.get(current);
        }
        if (current == destination) {
            cost= cost+allEdges.get(current);
            paths.add(new ArrayList<T>(path));

            cost= cost-allEdges.get(current);
            totalCost.add(cost);
            path.remove(current);
            return;
        }

        allEdges = graph.edgesFrom(current);

        final Set<T> edges  = graph.edgesFrom(current).keySet();

        for (T t : edges) {
            if (!path.contains(t)) {
                //System.out.println(t);
                recursiveWithCost (t, destination, paths, path,totalCost,cost , allEdges);
            }
        }

        path.remove(current);
    }    


    public static void main(String[] args) {
        GraphFindAllPaths<String> graphFindAllPaths = new GraphFindAllPaths<String>();
        graphFindAllPaths.addNode("A");
        graphFindAllPaths.addNode("B");
        graphFindAllPaths.addNode("C");
        graphFindAllPaths.addNode("D");

        graphFindAllPaths.addEdge("A", "B", 10);
        graphFindAllPaths.addEdge("A", "C", 15);
        graphFindAllPaths.addEdge("B", "A", 10);
        graphFindAllPaths.addEdge("C", "A", 15);
        graphFindAllPaths.addEdge("B", "D", 10);
        graphFindAllPaths.addEdge("C", "D", 20);
        graphFindAllPaths.addEdge("D", "B", 10);
        graphFindAllPaths.addEdge("D", "C", 20);

        graphFindAllPaths.addEdge("B", "C", 5);
        graphFindAllPaths.addEdge("C", "B", 5);



        FindAllPaths<String> findAllPaths = new FindAllPaths<String>(graphFindAllPaths);

        System.out.println("All possible Paths : ");
        for (List<String> path :findAllPaths.getAllPaths("D", "A"))
        {
            System.out.println(path);
        }

        System.out.println("\nAll possible paths with total distance : ");
        Map<List<String>,Double> pathWithCost = findAllPaths.getAllPathsWithCost("D", "A");
        for(Entry<List<String>, Double> s : pathWithCost.entrySet()){
            System.out.println(s);
        }

        // assertEquals(paths, findAllPaths.getAllPaths("A", "D"));
    }


}