【问题标题】:Get Main Line From Graph从图中获取主线
【发布时间】:2016-03-02 14:42:11
【问题描述】:

我正面临一个需要某种算法的问题,该算法允许我从图表中获取主线。主线基本上是一个支线网络。在图表上,它将是提供子节点的主节点。下图说明。

所以上图中的主线将是 1、2、3、4、5。每个节点包含一个属性,即连接节点列表;所以数字 3 将包含 2、4 和 10。我开始认为首先我应该摆脱与它们相连的节点,但这也会给我留下一些不需要的节点,因此如果我要删除 6 , 7, 8 ,9, 11, 13, 12 我仍然有一个不需要的节点 10。

对于那些不了解馈线网络是什么的人来说,它基本上是一堆结构、人孔、手孔、机柜,它们携带来自根结构1 的信号通过 2、3 分配到区域、4 和 5,直到它到达客户手中。 6, 7, 8, 11, 13, 12, 9. 至于10,它是一个子沙井结构,因为它分布在分支内部,所以根本不属于主网络的一部分。现在我知道那些是什么,但在代码中。这些只不过是一堆包含它们所连接的对象的对象。没有类型,什么都没有。

【问题讨论】:

  • 你的意思是图的直径吗?
  • 你知道路径或开始/结束节点吗?目前尚不清楚为什么1(而不是6)是开始节点而5 是结束(而不是例如4)。用什么标准来确定主线
  • 我希望代码是通用的,而不是依赖于类型 - 那么如何在 [1] 和 (6) 之间做出决定?你还是不清楚。
  • 解决问题的第一步是正确回答问题。
  • 你需要更好地定义主线是什么。显然你不希望它是最长的线,否则它将包括 6 和 12 或 13。但它也不仅仅是一个不是端节点的节点,否则将包括 10。

标签: algorithm networking graph nodes diagram


【解决方案1】:

根据您给出的部分答案,我认为添加另一个属性将为您提供解决方案。

到目前为止,您有 1、2、3、4、5 和 10。

问题是 10,正如我们所知,不应该是馈线网络的一部分(因为它是一个分支)。

如果您回头看,您可以看到,对于除 10 之外的所有节点,有一条从节点到源的路径和一条从节点到目的地的路径(您通过队列中的进程选择的最后一个节点)没有任何边缘被访问两次。

例如:

1.) 3->2->1(源)和 3->4->5(目标)

2.) 4->3->2->1(源)和 4->5(目标)

但如果是 10,一条边将被访问两次。

如,

10->3->2->1 & 10->3->4->5

在这里,如您所见,边缘 10-3 被访问了两次,这在其他节点的情况下不会发生。

通过这个过程,任何不属于馈线网络的节点都将被丢弃。

根据提供的信息,这将提供正确的解决方案。

【讨论】:

  • 太棒了,我会试一试,但看起来这样可以解决问题,我会尝试并在多个网络上试一试,以了解它的运行情况。谢谢
【解决方案2】:

我建议您从起始节点递归搜索。通过您的节点下降,跟踪您已通过的节点数量。 保留 2 个数组(或链表),一个用于当前路径,一个用于最长路径。下降时将节点添加到当前数组,返回时将其删除。对最长路径数组执行相同操作,但仅在超出当前最长路径时添加。当您搜索整个图形时,删除数组中的最后一个节点(因为它不会成为主路径的一部分)。

可能有一种更有效的方法可以做到这一点,我将不得不考虑一下。

【讨论】:

  • 谢谢杰夫,我试试看。
【解决方案3】:

此代码为您返回主线:

static void Main()
{
    Node node1 = new Node(1, null);
    Node node6 = new Node(6, node1);
    Node node2 = new Node(2, node1);
    Node node7 = new Node(7, node2);
    Node node8 = new Node(8, node2);
    Node node3 = new Node(3, node2);
    Node node10 = new Node(10, node3);
    Node node8_ = new Node(8, node10);
    Node node11 = new Node(11, node10);
    Node node4 = new Node(4, node3);
    Node node5 = new Node(5, node4);
    Node node12 = new Node(12, node5);
    Node node13 = new Node(13, node5);

    List<List<Node>> MainLines = new List<List<Node>>();
    foreach (var i in Node.HighestRankNodes)
    {
        List<Node> m = new List<Node>();
        m.Add(i);
        Node j = i.Parent;
        while (j != null)
        {
            m.Insert(0, j);
            j = j.Parent;
        }
        MainLines.Add(m);
    }
    foreach (var i in MainLines) Console.WriteLine("Mainline: " + string.Join(", ", i));
    Console.ReadLine();
}

节点类:

public class Node
{
    public int Number;
    public Node Parent = null;
    public int Rank = 0;

    public static int currentMaxRank = 0;
    public static List<Node> HighestRankNodes = new List<Node>();

    public Node(int number, Node parent)
    {
        Number = number;
        Parent = parent;
        Rank = Parent != null ? Parent.Rank + 1 : 0;
        if (currentMaxRank < Rank)
        {
            currentMaxRank = Rank;
            HighestRankNodes.Clear();
        }
        if (currentMaxRank == Rank) HighestRankNodes.Add(this);
    }

    public override string ToString()
    {
        return Number.ToString();
    }
}

输出:

Mainline: 1, 2, 3, 4, 5, 12
Mainline: 1, 2, 3, 4, 5, 13

【讨论】:

  • 我不确定这是否是我要找的,结果是根据你计算的排名,但我不明白你是如何“根据什么?”排名的跨度>
  • @ZZZ Rank是根节点到那个节点的距离,当然你可以命名为Distance。每次将子节点 (child) 添加到节点 (parent) 时,排名为 child.Rank = parent.Rank + 1Node 1Rank(距离)= 0。Node 2 是节点 1 的子节点 => Rank = 0 + 1 = 1,依此类推。有意义吗? :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多