设E是给定的有向边集。假设已知E中的边可以形成有向树T,所有节点(根节点除外)只有1个度。问题是如何有效地遍历边集E,以便找到T中的所有路径?
例如,给定有向边集E = {(1,2),(1,5),(5,6),(1,4),(2,3)}。我们知道这样的集合E可以生成只有1度(有根节点)的有向树T.是否有任何快速方法来遍历边集E,以便按如下方式找到所有路径:
Path1 = {(1,2),(2,3)}
Path2 = {(1,4)}
Path3 = {(1,5),(5,6)}
顺便说一下,假设E中的边数是| E |,是否有找到所有路径的复杂性?
答案 0 :(得分:2)
我之前没有处理过这类问题。所以只试了一个简单的解决方案。看看这个。
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; } }
}
答案 1 :(得分:0)
我认为DFS(深度优先搜索)应该符合您的要求。在这看一下 - Depth First Search - Wikipedia。您可以定制它以您需要的格式打印路径。至于复杂性,由于树中的每个节点都有一个度数,因此树的边数被限制为 - | E | = O(| V |)。由于DFS的复杂度为O(| V | + | E |),因此整体复杂度为O(| V |)。
答案 2 :(得分:0)
我把这个问题作为我的任务的一部分。上面的绅士已正确指出使用pathID。您必须至少访问每个边缘一次,因此复杂性界限为O(V + E),但对于树E = O(V),因此复杂度为O(v)。我会给你一瞥,因为细节有点涉及 -
您将使用唯一ID标记每个路径,并且路径是增量值中的分配ID,例如0,1,2 ....路径的pathID是路径上边缘的权重之和。因此,使用DFS为路径分配权重。您可以先使用0作为边缘,直到遇到第一条路径,然后继续添加1,依此类推。您还必须争论正确性并正确分配权重。 DFS会做到这一点。