Search code examples
algorithmgraphgraph-algorithmminimum-spanning-tree

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


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?


Solution

  • 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; } }
    }