首页 > 试题广场 >

【模板】单源最短路2

[编程题]【模板】单源最短路2
  • 热度指数:15749 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给你一个无向图,图中包含 5000 个点 m 个边,任意两个点之间的距离是 w ,无重边或自环。请求出1号点到n号点的最短距离。

注意:图中可能存在孤立点,即存在点与任意点都没有边相连

如果1号点不能到达n号点,输出-1.



输入描述:
第一行两个整数n和m,表示图的点和边数。
接下来m行,每行三个整数u,v, w,表示u到v有一条无向边, 长度为w。


输出描述:
输出一行,表示1到n的最短路,如不存在,输出-1.

示例1

输入

4 4
1 2 3
2 4 7
3 4 5
3 1 3

输出

8
示例2

输入

4 3
1 2 5
2 3 3
3 1 3

输出

-1

说明

1号点不能到4号点。
题目中的 n 并不是点的数目,而是终点序号。真正点的数目是 5000 !😂
发表于 2022-06-04 16:53:55 回复(10)
有的测试用例的边数大于m,只能取前m条边,需要注意
发表于 2022-12-05 12:30:56 回复(1)
from collections import defaultdict
import heapq
n, m = map(int, input().split())
G = defaultdict(set)
for i in range(m):
    u, v, w = map(int, input().split())
    G[u].add((v, w))
    G[v].add((u, w))
# print(G)
distances = {v: float("inf") for v in G}
# print(distances)
start = 1
distances[start] = 0
heap = [(0, start)]
heapq.heapify(heap)
while heap:
    distance, node = heapq.heappop(heap)
    # print(node)
    if distance > distances[node]:
        continue
    for neighbor, weight in G[node]:
        alt = distance + weight
        if distances[neighbor] > alt:
            distances[neighbor] = alt
            heapq.heappush(heap, (alt, neighbor))
# print(distances)
t = distances[n] if n in distances else -1
print( -1 if t is float("inf") else t )

发表于 2025-05-13 17:11:52 回复(0)
import java.util.*;

// Dijstra:这里注意点最大5000 可能大于n, 嫌麻烦直接开5000长度
public class Main {
    private static int INF = Integer.MAX_VALUE;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt(), m = in.nextInt();
        List<List<int[]>> g = new ArrayList<>(); // 邻接表
        for (int i = 0; i <= 5000; i++) g.add(new ArrayList<>());
        while (m-- > 0) {
            int u = in.nextInt(), v = in.nextInt(), w = in.nextInt();
            g.get(u).add(new int[] {v, w});
            g.get(v).add(new int[] {u, w});
        }
        
        int[] dis = new int[5001]; // dis[i]为 点1 → 点i 的最短路径长度
        Arrays.fill(dis, INF);
        dis[1] = 0;

        PriorityQueue<int[]> queue = new PriorityQueue<>((a, b)->a[1] - b[1]); // 最小堆
        queue.offer(new int[] {1, dis[1]});

        while (!queue.isEmpty()) {
            int[] a = queue.poll();
            int u = a[0], dis1u = a[1];
            if (dis1u > dis[u]) continue; // 之前已经访问过该点u了

            for (int[] b : g.get(u)) { // 尝试更新与 u 相邻的点
                int v = b[0], w = b[1];
                int newDis = dis[u] + w;
                // System.out.printf("%d %d %d\n", u ,v, newDis);
                if (dis[v] > newDis) {
                    // if (v == n) { // 找到n 直接返回? 不行,可能两个dis[]相同,都能到n,测试用例1
                    //     System.out.println(newDis);
                    //     return;
                    // }
                    dis[v] = newDis;
                    queue.offer(new int[] {v, newDis});
                }
            }
        }
        System.out.println(dis[n] == INF ? -1 : dis[n]); // 未找到?
    }
}

发表于 2025-05-07 16:30:34 回复(0)
import heapq
n, m = map(int,input().strip().split())
graph = [[] for _ in range(5001)]
for _ in range(m):
    u,v,w = map(int,input().strip().split())
    graph[u].append((v,w))
    graph[v].append((u,w))
dist = [float('inf')]*(5001)
dist[1] = 0
pq = [(0,1)]  # heap中排序的顺序是基于元组中第一个元素的,所以距离在前
while pq:
    d, u = heapq.heappop(pq)
    for v,w in graph[u]:
        if dist[u]+w < dist[v]:
            dist[v] = dist[u] + w
            heapq.heappush(pq,(dist[v],v))
print(dist[n] if dist[n]!=float('inf') else -1)
哪个**出的题,示例全是坑,示例2和8报错的需要注意n是目标点而不是点的总数!而u和v又是从1开始的,所以初始化邻接矩阵的时候就定其长度为5001
编辑于 2025-04-08 20:41:06 回复(0)
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int findmin(int visit[],int dist[],int n){
    int i=0,min=INT_MAX,index;
    for (i=0; i<n; i++) {
         if(!visit[i]&&dist[i]<min){
            index=i;
            min=dist[i];
        }
    }
    return index;
}
int dijkstra(int** g,int src,int end,int n){
    int i=0,u,k=1,j;
    int dist[n],visit[n],min=INT_MAX,path[n];
    for (i=0; i<n; i++) {
        visit[i]=0,dist[i]=min;
    }
    dist[src]=0;
    for (i=1; i<n; i++) {
        u=findmin(visit,dist, n);
        visit[u]=1,path[k++]=u;
        for (j=1;j<n; j++) {
           if(!visit[j]&&g[u][j]&&(dist[u]+g[u][j]<dist[j])){
                 dist[j]=dist[u]+g[u][j];
           }
        }
    }
    if (dist[end]==min) {
        printf("-1");
    }
    else {
        printf("%d",dist[end]);
    }
    return 0;
}
int main() {
    int n,m,i,j,k,a,b,c;
    scanf("%d%d",&n,&m);
    k=n+1;
    int **g=(int**)malloc(sizeof(int*)*5001);
    for (i=0; i<5001; i++) {
        g[i]=(int *)malloc(sizeof(int)*5001);
    }
    for(i=0;i<5001;i++){
        for (j=0;j<5001;j++) {
            g[i][j]=0;
             
        }
    }
    for (i=0; i<m; i++) {
        scanf("%d%d%d",&a,&b,&c);
        g[a][b]=c;
        g[b][a]=c;
    }
    dijkstra(g, 1, k-1, 5001);
    return 0;
 
}

发表于 2024-11-20 20:04:35 回复(0)
这题目出的纯纯有点**
编辑于 2024-08-30 16:15:31 回复(0)
我这用例8怎么过不了鸭, 是哪里的问题啊

import heapq
import sys

n, m = map(int, input().split())

# 使用字典来存储图的邻接表
graph = {}

# 读取输入的边信息
for line in sys.stdin:
    u, v, w = map(int, line.split())

    # 初始化字典键,如果不存在则初始化为空列表
    if u-1 not in graph:
        graph[u-1] = []
    if v-1 not in graph:
        graph[v-1] = []

    # 由于是无向图,双向添加边
    graph[u-1].append((v-1, w))
    graph[v-1].append((u-1, w))

# 初始化距离字典,所有节点的初始距离为无穷大
dist = {node: float('inf') for node in graph}
dist[0] = 0  # 起点的距离为0

# 初始化最小堆,开始Dijkstra算法
mini_heap = [(0, 0)]  # (距离, 节点)

while mini_heap:
    current_dist, u = heapq.heappop(mini_heap)
    
    # 如果当前节点的距离已经大于记录的最短距离,跳过
    if current_dist > dist[u]:
        continue
    
    # 更新邻居节点的距离
    for v, weight in graph[u]:
        if dist[u] + weight < dist[v]:
            dist[v] = dist[u] + weight
            heapq.heappush(mini_heap, (dist[v], v))

        # # Debug: 打印更新信息
        # print(f"Updated dist[{v}] to {dist[v]} via {u} with edge weight {weight}")

# 输出从节点 1 到 n 的最短距离,如果不可达则返回 -1
if n-1 in dist and dist[n-1] != float('inf'):
    print(dist[n-1])
else:
    print(-1)


发表于 2024-08-16 16:58:48 回复(2)
#include <algorithm>
#include <climits>
#include <iostream>
#include <vector>
#include <array>
using namespace std;

struct chartItem {
    chartItem() {
        index = 0;
        isSet = false;
        cost = INT_MAX;
        preIndex = 0;
    }
  public:
    int index;
    bool isSet;
    int cost;
    int preIndex;
};
int main() {
    //我的程序可以顺便把最短路径输出出来
    const int N = 5000;
    int G[N + 1][N + 1];
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            G[i][j] = INT_MAX;
        }
    }

    vector<chartItem> chart(N + 1);
    for (int i = 1; i <= N; i++) {
        chart[i].index = i;
    }
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        G[u][v] = w;
        G[v][u] = w;
    }

    chart[1].cost = 0;
    for (int i = 1 ; i <= N; i++) {
        //cout<< "the num cycle :"<< i<<endl;
        int indexMin = 0;
        int minCost = INT_MAX;
        for (int j = 1; j <= N; j++) {
            if (chart[j].cost < minCost && chart[j].isSet == false) {
                minCost = chart[j].cost;
                indexMin = j;
            }
        }
        if (indexMin != 0)chart[indexMin].isSet = true;
        //cout<< "cur  indexMin:"<< indexMin<<" minCost:"<<minCost<<endl ;
        if (indexMin == n) {
            // 当需要找的点找到最短路径时候,结束。
            break;
        }
        for (int j = 1; j <= N  ; j++) {
            if (G[indexMin][j] < INT_MAX && chart[j].isSet == false) {
                int cost1 = chart[indexMin].cost + G[indexMin][j];
                if (cost1 < chart[j].cost ) {
                    chart[j].cost = cost1;
                    chart[j].preIndex = indexMin;
                    //cout << indexMin <<"-"<<j <<":"<<cost1 <<" "<<"preIndex:"<<indexMin<<endl;
                }
            }
        }

    }
    if (chart[n].cost < INT_MAX)cout << chart[n].cost;
    else cout << -1;

    //下面是输出最短路径的代码
    /*int i = n;
    cout<<"  path: "<< n;
    while(chart[i].preIndex !=0){
        cout<<"<";
        cout<<chart[i].preIndex;
        i = chart[i].preIndex;
    }
    */
    return 0;
}
// 64 位输出请用 printf("%lld")
发表于 2024-06-06 15:02:35 回复(0)
package main

import (
	"fmt"
	"math"
)

//记录1号点到其他点的距离变化过程
var dj [][]int
//记录结果,
var ans []int
//邻接矩阵记录图的信息
var g [][]int
//当作栈使用,记录最新添加进来的顶点
var visit []int
//记录状态
var staue []bool
//初始化邻接矩阵
func create(n, m int, cost [][]int){
    g = make([][]int, n + 1)
    for i := range g{
        g[i] = make([]int, n + 1)
        for j := range g[i]{
            g[i][j] = math.MaxInt
        }
    }
    for i := 0; i < m; i++{
        g[cost[i][0]][cost[i][1]], g[cost[i][1]][cost[i][0]] = cost[i][2], cost[i][2]
    }
}
func solve(n, m int){
    //初始化dj数组
    dj = make([][]int, n + 1)
    for i := range dj{
        dj[i] = make([]int, n + 1)
    }
    //初始化第一列
    for i := 2; i <= n; i++{
        dj[i][2] = g[1][i]
    }
    //初始化ans数组
    ans = make([]int, n + 1)
    //初始化连接数组
    visit = []int{}
    visit = append(visit, 1)
    //初始化状态数组
    staue = make([]bool, n + 1)
    staue[1] = true
    var min, minR int
    //n个点循环n-1次即可寻找到最短路径
    for i := 2; i <= n; i++{
        //每次初始化最小值为无穷大
        min = math.MaxInt
        minR = 0
        //遍历列寻找最小值
        for j := 2; j <= n; j++{
            if !staue[j] && dj[j][i] < min{
                min = dj[j][i]
                minR = j
            }
        }
        if min != math.MaxInt && i != n{
            ans[minR] = min
            staue[minR] = true
            visit = append(visit, minR)
            //加入新顶点后更新最短路径,即后一列
            for k := 2; k <= n; k++{
                newPath := g[visit[len(visit) - 1]][k]
                if newPath == math.MaxInt{
                    dj[k][i + 1] = dj[k][i]
                } else {
                    if newPath + min < dj[k][i]{
                        dj[k][i + 1] = newPath + min
                    } else {
                        dj[k][i + 1] = dj[k][i]
                    }
                }
            }
        } else if min != math.MaxInt && i == n{
            ans[minR] = min
            staue[minR] = true
            visit = append(visit, minR)
        } else if min == math.MaxInt && i == n{
            ans[minR] = -1
        } else {
            //如果最小值是无穷大且不是最后一列,说明多个点不可达,遍历结果数组将结果为初始值的赋值为-1并退出循环
            for i := 2; i <= n; i++{
                if ans[i] == 0{
                    ans[i] = -1
                }
            }
            break
        }
    }
}
func main() {
    var n, m int
    fmt.Scan(&n, &m)
    //cost数组记录边
    cost := make([][]int, m)
    for i := range cost{
        cost[i] = make([]int, 3)
    }
    for i := 0; i < m; i++{
        fmt.Scan(&cost[i][0], &cost[i][1], &cost[i][2])
    }
    create(5000, m, cost)
    solve(5000, m)
    fmt.Println(ans[n])
}只有最后一组用例不能通过,不知道什么问题,输入5000,20000,预期-1,实际0,找不到还有-1的情况了
编辑于 2024-04-23 21:37:53 回复(0)
#include<iostream>
#include<climits>
#include<vector> // 使用INT_MAX所需要引入的头文件
using namespace std;
int main()
{
    const int N = 5000; // 注意题干,图的点数是固定值5000
    vector<vector<int>> G(N+1,vector<int>(N+1)); // 用于模拟邻接矩阵进行建图
    for(int i = 1; i <= N; i++)
    {
        for(int j = 1; j <= N; j++)
        {
            G[i][j] = INT_MAX; // 先将邻接矩阵全部初始化为无穷大
        }
    }
    int n, m;
    cin>>n>>m;
    int u, v, w;
    for(int i = 1; i <= m; i++)
    {
        cin>>u>>v>>w;
        G[u][v] = w;G[v][u] = w; // 注意为无向图,需要关于主对角线对称,因此两边都需要存储
    }
    vector<int> dist(N+1); // 用于存储每个顶点当前与源点的最短距离
    vector<bool> flag( N+ 1); // 用于记录每个顶点是否已经完成与源点最短距离的计算处理
    for(int i = 2; i <= N; i++)
    {
        dist[i] = G[1][i];flag[i] = false;
    }
    dist[1] = 0;flag[1] = true; // 将源点加入已处理集合
    for(int i = 2; i <= N; i++)
    {
        int tmp = INT_MAX, index = 1;
        for(int j = 2; j <= N; j++) // 遍历寻找与源点的最短距离
        {
            if(flag[j] == false && dist[j] < tmp)
            {
                tmp = dist[j];
                index = j;
            }
        }
            flag[index] = true; // 找到后将其加入已处理集
        for(int j = 2; j <= N; j++)
        {
            if(flag[j] == false && G[index][j] != INT_MAX)
            {
                if(G[index][j] + dist[index] < dist[j])
                {
                    dist[j] = G[index][j] + dist[index]; // 新的距离比原距离更短,则进行更新
                }
            }
        }
    }
    if(dist[n] != INT_MAX)
    {
        cout<<dist[n];
    }
    else // 没有从源点到达该顶点的边
    {
        cout<<-1;
    }
    return 0;
}

编辑于 2024-04-13 17:08:21 回复(0)
采用最笨的方法,没有那么多的优化
#include <stdio.h>
#include <string.h>

typedef struct graph {
    int matrix[5000][5000];
} graph;

//-1表示无穷大
void init_graph(graph* g) {
    memset(g->matrix, -1, sizeof(g->matrix));
}

void add_edge(graph* g, int start, int end, int cost) {
    if (g->matrix[start - 1][end - 1] > cost || g->matrix[start - 1][end - 1] == -1) {
        g->matrix[start - 1][end - 1] = cost;
        g->matrix[end - 1][start - 1] = cost;
    }
}

//采用dijkstra算法
int dijkstra(graph* g, int start, int end) {
    if(start == end){
        return 0;
    }
    char final[5000];
    memset(final, 0, sizeof(final));
    int distance[5000];
    memset(distance, -1, sizeof(distance));
    int path[5000];
    memset(path, -1, sizeof(path));

    //初始化距离矩阵
    final[start - 1] = 1;
    for (int i = 0; i < 5000; i++) {
        distance[i] = g->matrix[start - 1][i];
    }
    int visited = 1,temp;
    while (visited != 5000) { //还有节点没有加入
        //选择一个到达start的距离最小的且final[]为0的节点
        int cost = -1,idx = -1;
        for (int i = 0 ; i < 5000; i++) {
            if (final[i] == 0 && distance[i] != -1) {
                if(cost == -1 || distance[i] < cost){ 
                    cost = distance[i];
                    idx = i;
                }
            }
        }
        if (idx != -1){
            //将这个点加入final
            final[idx] = 1;
            //计算其他节点同选择的idx节点的距离
            for (int i = 0 ; i < 5000; i++) {
                if (final[i] == 0) {
                    if(g->matrix[i][idx]  != -1 && distance[idx] != -1){
                        temp = g->matrix[i][idx] + distance[idx];
                        if(distance[i] == -1 || temp < distance[i]){ //目标距离start无穷大
                            distance[i] = temp;
                            path[i] = idx;
                        }
                    }
                    
                }
            }
        } else {
            //不需要找了,找不到,全是无穷大的不可到达的点
            break;
        }
        visited++;
    }
    if (path[end - 1] != -1 ) {
        return distance[end - 1];
    }
    return -1;
}

int main() {
    int n,m,start,end,cost;
    scanf("%d%d",&n,&m);
    graph g;
    init_graph(&g);
    for(int i = 0 ; i < m;i++){
        scanf("%d%d%d",&start,&end,&cost);
        add_edge(&g, start, end,cost);
    }
    int ret = dijkstra(&g, 1, n);
    printf("%d\n",ret);
    return 0;
}

编辑于 2024-02-17 15:45:33 回复(0)
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
#define N 5000

int Dijsktra(int n, vector<vector<int>> Graph)
{
    //要构建三个数组
    //一个记录路径大小 Distance
    //一个记录是否已有最小路径 Flag
    //一个记录该点最小路径的前一个点 Previous
    vector<int> Distance;
    vector<bool> Flag(N, false);
  //  vector<int> Previous(N, 0);

    Distance.emplace_back(0);
    for(int i = 1; i < N; i++)
        Distance.emplace_back(Graph[0][i]);
    Flag[0] = true;

    int current = 0 , min;
    for(int i = 1; i < N; i++)
    {
        //当前Distance最小的一个点,即为0到该点的最短路径
        min = INT_MAX;
        for(int j = 0; j < N; j++)
        {
            if( !Flag[j] && Distance[j] < min)
            {
                current = j;
                min = Distance[j];
            }
        }
        Flag[current] = true;

        //更新Distance
        for(int j = 0; j < N; j++)
        {
            //添加条件 Graph[current][j] != INT_MAX以防止溢出
            if( !Flag[j] && Graph[current][j] != INT_MAX && (Graph[current][j] + min < Distance[j] ) )
            {
                Distance[j] = Graph[current][j]+min;
      //          Previous[j] = current;
            }
        }
    }
    //路径仅作练习
    // for(int i = 1; i < N; i++)
    // {
    //     if(!Flag[i])
    //         cout << "0 -> " << i <<" : 不可到达!"<< endl; 
    //     else
    //     {
    //         int x = i;
    //         cout << "0 -> " << i <<" : "<< Distance[i]<<endl;
    //         cout<<" Path: " << i ;
    //         while(Previous[x] != 0)
    //         {
    //             cout << " <- " <<Previous[x];
    //             x = Previous[x];
    //         }
    //         cout <<" <- " <<0 <<endl;
    //     }
    //     cout<<endl;
    // }

    if(Flag[n-1])
        return Distance[n-1];
    return -1;

}

int main() {
    int n, m;
    cin>>n>>m;
    vector<vector<int>> Graph(N, vector<int>(N, INT_MAX));
    int u, v, w;
    while(m--)
    {
        cin >> u >> v >> w;
        Graph[u-1][v-1] = Graph[v-1][u-1] = w;
    }
    int result;
    result = Dijsktra(n,Graph);
    cout << result <<endl;
}


发表于 2023-10-27 21:44:41 回复(0)
#include <limits.h>
#include <malloc.h>
#include <stdio.h>

#define MAX 5000

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    //使用二维数组存储边的权值,并且行标表示出发点,列标表示到达点
    int map[MAX+1][MAX+1]={0};
    for (int i = 1; i <= MAX; i++) {
        for (int j = 1; j <= MAX; j++) {
                map[i][j] = INT_MAX;
        }
    }
    int u, v, w;
    for (int i = 0; i < m; i++) { // 注意 while 处理多个 case
        scanf("%d %d %d", &u, &v, &w);
        map[u][v] = w;
        map[v][u] = w;
    }

    //Dijkstra算法
    //初始化
    //S表示集合,为1表示在集合中,为0表示不在集合中
    int dist[MAX+1]={0};
    int S[MAX+1]={0};

    for (int i = 1; i <= MAX; i++) {
        dist[i] = map[1][i];
        S[i]=0;
    }
    S[1] = 1;
    dist[1] = 0;

    for(int i=2;i<=n;i++) {
        int min = INT_MAX, min_p=1;
        //找到最小dist
        for (int j = 1; j <=MAX; j++) {
            if (S[j]==0 && min > dist[j]) {
                min = dist[j];
                min_p = j;
            }
        }

        //将min_p节点纳入S
        if(min_p!=1){
            S[min_p]=1;
        }

        for (int j = 1; j <=MAX; j++) {
            if (S[j] == 0 && map[min_p][j] != INT_MAX) { //未纳入S的点,且i能到达j
                int check = map[min_p][j]+dist[min_p];
                //如果1到j的路径较大,则更新
                if (dist[j] > check) {
                    dist[j] = check;
                }
            }
        }
        
    }

    if(dist[n]!=INT_MAX)
        printf("%d", dist[n]);
    else
        printf("-1");
    return 0;
}

发表于 2023-07-20 17:18:52 回复(0)
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    let [n,m]=(await readline()).split(" ").map(it=>parseInt(it));
    let INF=+Infinity;
    let mat=new Array(5001).fill(0).map(()=>new Array(5001).fill(INF));
    while(m--){
        let [u,v,w]=(await readline()).split(" ").map(it=>parseInt(it));
        mat[u][v]=w;
        mat[v][u]=w;
    }
    let dist=new Array(5001).fill(INF);
    dist[1]=0;
    let vis=new Array(5001).fill(false);
    for(let i=1;i<=5000;i++){
        let x=-1;
        for(let y=1;y<=5000;y++){
            if(!vis[y]&&(x==-1||dist[y]<dist[x])){
                x=y;
            }
        }
        vis[x]=true;
        for(let y=1;y<=5000;y++){
            if(mat[x][y]==INF) continue;
            if(!vis[y]) dist[y]=Math.min(dist[y],dist[x]+mat[x][y]);
        }
    }
    console.log(dist[n]==INF?-1:dist[n]);
}()

发表于 2022-12-24 00:36:37 回复(0)
//迪杰斯特拉算法,Java,为什么老是有部分用例通不过啊,人都麻了
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public final static int MAX_INT = 10000;
    public static void main(String[] args) {
        final int N = 5000;
        int[][] graph = new int[N + 1][N + 1];
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                graph[i][j] = MAX_INT;
            }
        }
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        for (int i = 0; i < m; i++) {
            int v = scanner.nextInt();
            int w = scanner.nextInt();
            int weight = scanner.nextInt();
            graph[v][w] = weight;
            graph[w][v] = weight;
        }

        shortestPath_DIJ(graph, 1, n);

    }

    public static void shortestPath_DIJ(int[][] graphint v0int n) {
        int N = 5000;
        //从源点v0到终点vi是否被确定最短路径
        boolean[] S = new boolean[N + 1];
        //从源点v0到终点vi当前路径权值
        int[] D = new int[N + 1];
        //从源点v0到终点vi当前路径vi得直接前驱
        int[] Path = new int[N + 1];
        for (int i = 1; i <= N; i++) {
            S[i] = false;
            D[i] = graph[v0][i];
            if (D[i] < MAX_INT)
                Path[i] = v0;
            else
                Path[i] = -1;
        }

        S[v0] = true;
        D[v0] = 0;
        for (int i = 2; i <= N; i++) {
            int min = MAX_INT;
            int v = v0;
            for (int w = 1; w <= N; w++) {
                if (!S[w] && D[w] < min) {
                    v = w;
                    min = D[w];
                }
            }
            S[v] = true;
            //更新相关集合
            for (int w = 1; w <= N; w++) {
                if (!S[w] && (D[v] + graph[v][w] < D[w])) {
                    D[w] = D[v] + graph[v][w];
                    Path[w] = v;
                }
            }
        }

        if (S[n])
            System.out.print(D[n]);
        else
            System.out.print(-1);
    }

}

发表于 2022-11-17 11:36:34 回复(0)