LeetCode基础-图-有向图-最短路径

最短路径:从图中的一个顶点到另一个顶点的成本最小的路径。
单点最短路径:在加权有向图中,给出一个起点 s,找到是否有一条到顶点 v 的路径,如果有,找出权重最小的那条。

这里写图片描述

最短路径的性质:

  • 路径是有向的。
  • 权重不定表示距离。
  • 并不是所有顶点都是可达的。
  • 负权重会使问题变复杂。
  • 最短路径一般都是简单的(不含零权重边的环)。
  • 最短路径不定是唯一的。
  • 可能存在平行边和自环。平行边中权重最小的才会被选中。也不包含自环(除非自环的权重为零)

最短路径树(SPT):在加权有向图中,有一个顶点 s,以 s 为起点的最短路径树是图的一幅子图,包含 s 和从 s 到达的所有顶点。这棵树的根结点是 s,树的每条路径都是有向图中的一条最短路径。

这里写图片描述

加权有向边的数据结构:

public class DirectedEdge
{
    private final int v; // edge source
    private final int w; // edge target
    private final double weight; // edge weight

    public DirectedEdge(int v, int w, double weight)
    {
        this.v = v;
        this.w = w;
        this.weight = weight;
    }

    public double weight()
    { return weight; }

    public int from()
    { return v; }

    public int to()
    { return w; }

    public String toString()
    { return String.format("%d->%d %.2f", v, w, weight); }
}

加权有向图的数据结构:

public class EdgeWeightedDigraph
{
    private final int V; // number of vertices
    private int E; // number of edges
    private Bag<DirectedEdge>[] adj; // adjacency lists

    public EdgeWeightedDigraph(int V)
    {
        this.V = V;
        this.E = 0;
        adj = (Bag<DirectedEdge>[]) new Bag[V];
        for (int v = 0; v < V; v++)
        {
            adj[v] = new Bag<DirectedEdge>();
        }
    }

    public int V() { return V; }

    public int E() { return E; }

    public void addEdge(DirectedEdge e)
    {
        adj[e.from()].add(e);
        E++;
    }
    public Iterable<Edge> adj(int v)
    { return adj[v]; }

    public Iterable<DirectedEdge> edges()
    {
        Bag<DirectedEdge> bag = new Bag<DirectedEdge>();
        for (int v = 0; v < V; v++)
        {
            for (DirectedEdge e : adj[v])
            {
                bag.add(e);
            }
        }
        return bag;
    }
}

如下图:

这里写图片描述

最短路径的数据结构:

这里写图片描述

  • 最短路径树中的边:使用一个由顶点索引的DirectedEdge对象的父连接数组edgeTo[],edgeTo[v] 的值是树中连接 v 和它的父结点的边(也是 s 到 v 的最短路径上的最后一条边。edgeTo[s] = null;
  • 到达起点的距离:一个由顶点索引的数组 distTo[],其中 distTo[v] 是从 s 到 v 的已知最短路径的长度。distTo[s] = 0;

边的松驰(Relaxation)
定义:要放松(relax)一条边 v->w,意味着检查从
s 到 w 的最短路径是否是先从 s 到 v,然后从 v 到 w,如果是,则更新数据结构的内容。

private void relax(DirectedEdge e)
{
    int v = e.from();
    int w = e.to();
    if (distTo[w] > distTo[v] + e.weight())
    {
        distTo[w] = distTo[v] + e.weight();
        edgeTo[w] = e;
    }
}

边的松驰的两种情况:
一种是边失效,不更新数据。图左。
一种是 v -> w 就是到达 w 的最短路径。图右。

这里写图片描述

顶点的松驰(Relaxation)
顶点的松驰即是放松一个顶点的所有出边。

private void relax(EdgeWeightedDigraph G, int v) 
{
    for (DirectedEdge e : G.adj(v)) 
    {
        int w = e.to();
        if (distTo[w] > distTo[v] + e.weight()) 
        {
            distTo[w] = distTo[v] + e.weight();
            edgeTo[w] = e;
        }
    }
}

如下图:

这里写图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值