NC158 单源最短路径

方法一: floyd

1.定义

(1)Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。
(2)思想: 动态规划(dp),而求最短路径需要不断松弛(熟悉spfa算法的可能熟悉松弛)。

2.算法具体思想

(1)邻接矩阵dist储存路径,同时最终状态代表点的最短路径。如果没有直接相连的两点那么默认为一个很大的值(不要溢出)!而自己的长度为0.
(2)从第1个到第n个点依次加入图中。每个点加入进行试探是否有路径长度被更改。
--上述试探具体方法为遍历图中每一个点(i,j双重循环),判断每一个点对距离是否因为加入的点而发生最小距离变化。
--如果发生改变,那么两点(i,j)距离就更改。
--重复上述直到最后插点试探完成。
(3)dp[x][y]的意思可以理解为x到y的最短路径, 其中第三步的状态转移方程为: dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])

#3.方法1 floyd 
import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int 顶点数
     * @param m int 边数
     * @param graph int二维数组 一维3个数据,表示顶点到另外一个顶点的边长度是多少
     * @return int
     */
    int N = 510, M = 5010; // 节点最大数量, 边最大数量
    int INF = 0x3f3f3f3f; // 无穷大
    // 邻接矩阵数组 w[x][y] = z 代表从 x节点 到 y节点 有权重为 c 的边
    int[][] w = new int[N][N];
    public int findShortestPath (int n, int m, int[][] graph) {
        // 1.初始化邻接矩阵
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                w[i][j] = w[j][i] = (i == j ? 0 : INF);
            }
        }
        
        // 2.存图
        for (int[] edge : graph) {
            int u = edge[0], v = edge[1], c = edge[2];
            w[u][v] = Math.min(w[u][v], c);
        }
       
        // 3.最短路floyd算法, 三层循环
        floyd(n);
        return w[1][n] >= INF / 2 ? -1 : w[1][n];
    }
    void floyd(int n) {
        //枚举中转点(p) - 枚举起点(x) - 枚举终点(y) - 松弛操作
        for (int p = 1; p <= n; p++) { // 新加入图中节点
            for (int x = 1; x <= n; x++) {
                for (int y = 1; y <= n; y++) {
                    // dp思想: 遍历图中每一个点(i,j双重循环)判断每一个点对距离是否因为加入的点
                    // 而发生最小距离变化。如果发生改变,那么两点(i,j)距离就更改。重复上述直到最后插点试探完成。
                    // w[x][p] + w[p][y] 这里p的顺序??
                    w[x][y] = Math.min(w[x][y], w[x][p] + w[p][y]);
                }
            }
        }
    }
}

方法二: dijkstra

1.算法思想

(1)通过Dijkstra计算图G中的最短路径(从顶点s开始计算)。
(2)引进两个集合S和U。
--S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),
--U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是”起点s到该顶点的路径”。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 … 重复该操作,直到遍历完所有顶点。

#4.方法二 dijkstra
import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int 顶点数
     * @param m int 边数
     * @param graph int二维数组 一维3个数据,表示顶点到另外一个顶点的边长度是多少
     * @return int
     */
    int N = 510, M = 5010; // 节点最大数量, 边最大数量
    int INF = 0x3f3f3f3f; // 无穷大
    // 邻接矩阵数组 w[x][y] = z 代表从 x节点 到 y节点 有权重为 c 的边
    int[][] w = new int[N][N];
    // dist[x] = y 代表 起点到 x 的最短距离为 y
    int[] dist = new int[N];
    // 记录哪些点已经被更新过
    boolean[] visited = new boolean[N];
    public int findShortestPath (int n, int m, int[][] graph) {
        // 1.初始化邻接矩阵
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                w[i][j] = w[j][i] = (i == j ? 0 : INF);
            }
        }
        
        // 2.存图
        for (int[] edge : graph) {
            int u = edge[0], v = edge[1], c = edge[2];
            w[u][v] = Math.min(w[u][v], c);
        }
       
        // 3.最短路dijkstra算法
        dijkstra(n);
        return dist[n] >= INF / 2 ? -1 : dist[n];
    }
    void dijkstra(int n) {
        // 1.初始化: 所有点标记为[未更新], [距离无穷大]
        Arrays.fill(visited, false);
        Arrays.fill(dist, INF);
        
        // 2.只有起点的最短距离为0
        dist[1] = 0;
        
        // 3.迭代n次
        for (int p = 1; p <= n; p++) { 
            // 3.1 每次找到 [未被更新] && [距离最小] 的节点t
            int t = -1;
            for (int i = 1; i <= n; i++) {
                if (!visited[i] && (t == -1 || dist[i] < dist[t])) {
                    t = i;
                }
            }
            
            // 3.2 标记为更新
            visited[t] = true;
            
            // 3.3 用t节点的[最短距离]去更新其他节点
            for (int i = 1; i <= n; i++) {
                dist[i] = Math.min(dist[i], dist[t] + w[t][i]);
            }
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容