Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 求(稀疏)图直径的好算法?_Algorithm_Math_Graph Theory - Fatal编程技术网

Algorithm 求(稀疏)图直径的好算法?

Algorithm 求(稀疏)图直径的好算法?,algorithm,math,graph-theory,Algorithm,Math,Graph Theory,我有一个大的,连通的,稀疏的邻接列表形式的图。我想找到两个尽可能远的顶点,也就是说,和两个顶点实现它 对于不同的应用,我对无向和定向情况下的这个问题都感兴趣。在有向情况下,我当然关心有向距离(从一个顶点到另一个顶点的最短有向路径) 有比计算所有对最短路径更好的方法吗? 编辑:我所说的“尽可能远”,当然是指“最长最短路径”——即从一个顶点到另一个顶点的最短距离的所有顶点对的最大值。编辑我再次取消删除,只是为了继续评论。在这个答案下面,我对约翰逊的算法有一些评论亚伦 我最初的评论是: 我对这个问题也

我有一个大的,连通的,稀疏的邻接列表形式的图。我想找到两个尽可能远的顶点,也就是说,和两个顶点实现它

对于不同的应用,我对无向和定向情况下的这个问题都感兴趣。在有向情况下,我当然关心有向距离(从一个顶点到另一个顶点的最短有向路径)

有比计算所有对最短路径更好的方法吗?

编辑:我所说的“尽可能远”,当然是指“最长最短路径”——即从一个顶点到另一个顶点的最短距离的所有顶点对的最大值。

编辑我再次取消删除,只是为了继续评论。在这个答案下面,我对约翰逊的算法有一些评论亚伦

我最初的评论是: 我对这个问题也很好奇,但没有答案。它似乎与连接所有顶点但具有最少(或最低权重)边的子图有关。这是一个有许多算法的老问题;其中一些似乎很容易实现


我最初希望,一旦找到MST,直径就会变得明显,但现在我失去了希望:-(也许MST可以用来为直径设置一个合理的上限,你可以用它来加速搜索实际直径?

好吧,我对这个问题进行了一点思考,用谷歌搜索了一下,很抱歉,但我找不到任何算法不是“只找到所有对的最短路径”

然而,如果你假设Floyd Warshall是计算这类东西的唯一算法(大θ为| V | ^3),那么我有一个好消息告诉你:Johnson的稀疏图算法(谢谢你,可靠的CLR!)计算(大Oh(|V | ^2*lgV+VE))中的所有对最短路径,对于稀疏图,这应该是渐进更快的

维基百科说它适用于directed(不确定是否为undirected,但至少我想不出一个不适用的理由),下面是答案

这个图还有什么有用的地方吗?如果它可以很容易地映射到二维平面上(因此,它的平面和边的权重服从三角形不等式[它可能需要满足更严格的要求,我不确定]),那么你可能能够解出一些几何算法(凸包可以在nlogn中运行,从那里很容易找到最远的点对)

希望这有帮助! -阿戈尔


编辑:我希望这个链接现在能正常工作。如果不行,就用谷歌搜索一下。:)

除了所有最短路径之外,我不知道还有什么更好的方法来计算直径,但Mathematica对伪直径使用了以下近似值:

  • 图测地线是最短路径 图的两个顶点之间 图形直径最长 所有图的可能长度 图的测地线。 伪直径找到一个近似值 图形直径。它通过启动来工作 从顶点u开始,并查找顶点v 那是离你最远的地方 该过程通过将v视为 新的起始顶点和结束点 当图形距离不再 增加。从上一个顶点开始的顶点 具有最小值的级别集 学位被选为期末考试 从顶点u开始,遍历为 完成以查看图形距离是否可以 此图形距离为 视为伪直径
肮脏的方法:

我们知道,对于| V |=n和| E |=m的图G(V,E),Dijkstra算法在
O(m+nlogn)
中运行,这是针对单个源的。对于所有对问题,需要对每个节点运行Dijkstra作为起点

但是,如果您有许多机器,则可以轻松地并行此过程


这种方法最容易实现,肯定不是很好。

下面是一些关于在无向图中比所有对最短路径做得更好的想法,尽管我不确定这会有多大的改进

这里有一个子程序,可以找到两个节点之间的距离D(如果有)。选择任意节点x并计算M[x]=从x到任何其他节点的最大距离(使用任何单源最短路径算法)。如果M[x]>=D,则x是我们的一个节点,另一个很容易找到。但是,如果M[x]
现在我们只需要设置D=diam(G)并运行上面的过程。我们不知道diam(G)是什么,但我们可以得到一个非常窄的范围,对于任何x,M[x]我真的怀疑是否有任何方法可以在不必使用某种全对最短路径算法的情况下找到最长最短路径(重复寻找单个源的最短路径基本上就是在最坏的情况下进行所有对)

如果图不是树或DAG,“直径”就很难用“最长路径”来定义。如果图中有循环,“最长”路径可以是无限的。因此,简单遍历图无法生成所有节点上的最长路径。因为您已经声明,您的图不一定是非循环的,并且您是inte基于“最长-最短”路径,似乎没有任何方法可以避免为所有节点找到最短路径。正如Agor所建议的,使用Johnson算法可能是最好的方法


当然,你可以使用基于启发式的方法。使用的算法似乎是最常用的方法。

如果我的答案在语法方面不正确,请原谅,但我的算法课程已经有一段时间了
public class MyTestClass
{
    //Simple Point struct
    struct Vertex
    {
        public float X, Y;
        public Vertex(float pX, float pY)
        {
            X = pX;
            Y = pY;
        }
    }

    //For getting the bounds of your graph
    struct BoundingBox
    {
        public float Left, Right, Bottom, Top;
        public BoundingBox(float pLeft, float pRight, float pBottom, float pTop)
        {
            Left = pLeft;
            Right = pRight;
            Bottom = pBottom;
            Top = pTop;
        }
    }

    //Properties
    Vertex[] vertices;
    BoundingBox bound;
    float diameter;

    //Constructor
    //Here is the fastest way to get the diameter >>
    public MyTestClass()
    {
        //Init objects
        vertices = new Vertex[100];
        for(int i = 0; i != vertices.Length; ++i) vertices[i] = new Vertex(i, i);
        bound = new BoundingBox(vertices[0].X, vertices[0].X, vertices[0].Y, vertices[0].Y);
        //Calculate BoundingBox
        for(int i = 0; i != vertices.Length; ++i)
        {
            bound.Left = (vertices[i].X <= bound.Left) ? vertices[i].X:bound.Left;
            bound.Right = (vertices[i].X >= bound.Right) ? vertices[i].X:bound.Right;
            bound.Bottom = (vertices[i].Y <= bound.Bottom) ? vertices[i].Y:bound.Bottom;//NOTE: If Y is faces down, then flip bottom & top comparison
            bound.Top = (vertices[i].Y >= bound.Top) ? vertices[i].Y:bound.Top;
        }
        //Messure Size of the BoundingBox
        float vecX = (bound.Right-bound.Left);
        float vecY = (bound.Top-bound.Bottom);
        diameter = (float)System.Math.Sqrt((vecX*vecX) + (vecY*vecY));
    }
}